@@ -605,12 +605,35 @@ public function testSanitizeTypeHandlesVariousEntityTypes(): void
605605 public function testParseUrlHandlesVariousUrlFormats (): void
606606 {
607607 $ testCases = [
608+ // Simple URL without leading slash
608609 'simple-url ' => ['path ' => 'simple-url ' ],
610+ // URL with leading slash (should be stripped)
609611 '/leading-slash ' => ['path ' => 'leading-slash ' ],
612+ // URL with query parameters
610613 'url-with-query?param=value ' => ['path ' => 'url-with-query ' , 'query ' => 'param=value ' ],
614+ // Complex path structure
611615 'complex/path/structure ' => ['path ' => 'complex/path/structure ' ],
616+ // Root URL (leading slash should be preserved)
612617 '/ ' => ['path ' => '/ ' ],
613- '' => ['path ' => '' ]
618+ // Empty string
619+ '' => ['path ' => '' ],
620+
621+ // URL with fragment
622+ 'path-with-fragment#section ' => ['path ' => 'path-with-fragment ' , 'fragment ' => 'section ' ],
623+ // URL with query and fragment
624+ '/path?query=value#fragment ' => ['path ' => 'path ' , 'query ' => 'query=value ' , 'fragment ' => 'fragment ' ],
625+ // URL with host (should preserve path parsing)
626+ 'https://example.com/path ' => ['scheme ' => 'https ' , 'host ' => 'example.com ' , 'path ' => 'path ' ],
627+ // URL with port
628+ 'http://example.com:8080/path ' => ['scheme ' => 'http ' , 'host ' => 'example.com ' , 'port ' => 8080 , 'path ' => 'path ' ],
629+ // URL with user info
630+ 'https://user:pass@example.com/path ' => ['scheme ' => 'https ' , 'user ' => 'user ' , 'pass ' => 'pass ' , 'host ' => 'example.com ' , 'path ' => 'path ' ],
631+ // Complex query string
632+ 'product?color=red&size=large&in_stock=1 ' => ['path ' => 'product ' , 'query ' => 'color=red&size=large&in_stock=1 ' ],
633+ // Path with encoded characters
634+ 'category/special%20products ' => ['path ' => 'category/special%20products ' ],
635+ // Multiple slashes in path
636+ '///multiple///slashes ' => ['path ' => 'multiple///slashes ' ]
614637 ];
615638
616639 $ reflection = new \ReflectionClass ($ this ->resolver );
@@ -623,6 +646,67 @@ public function testParseUrlHandlesVariousUrlFormats(): void
623646 }
624647 }
625648
649+ /**
650+ * Test parseUrl method with malformed URLs
651+ */
652+ public function testParseUrlHandlesMalformedUrls (): void
653+ {
654+ $ reflection = new \ReflectionClass ($ this ->resolver );
655+ $ method = $ reflection ->getMethod ('parseUrl ' );
656+ $ method ->setAccessible (true );
657+
658+ // Test cases where parse_url might return false or fail
659+ $ malformedUrls = [
660+ // Very malformed URL that might cause parse_url to return false
661+ "http:/// " ,
662+ // URL with invalid characters
663+ "test \x00url " ,
664+ // Extremely long URL (though this might not fail parse_url)
665+ str_repeat ('a ' , 2000 ),
666+ ];
667+
668+ foreach ($ malformedUrls as $ malformedUrl ) {
669+ $ result = $ method ->invoke ($ this ->resolver , $ malformedUrl );
670+ // Should always return an array with at least 'path' key
671+ $ this ->assertIsArray ($ result );
672+ $ this ->assertArrayHasKey ('path ' , $ result );
673+ // When parse_url fails, the path should be the original URL
674+ if (!is_array (parse_url ($ malformedUrl ))) {
675+ $ this ->assertEquals ($ malformedUrl , $ result ['path ' ]);
676+ }
677+ }
678+ }
679+
680+ /**
681+ * Test parseUrl method with edge cases for path normalization
682+ */
683+ public function testParseUrlPathNormalization (): void
684+ {
685+ $ reflection = new \ReflectionClass ($ this ->resolver );
686+ $ method = $ reflection ->getMethod ('parseUrl ' );
687+ $ method ->setAccessible (true );
688+
689+ // Test edge cases for path normalization
690+ $ testCases = [
691+ // Single slash should remain as is (root)
692+ '/ ' => ['path ' => '/ ' ],
693+ // Multiple leading slashes should be stripped to single path
694+ '/////path ' => ['path ' => 'path ' ],
695+ // Leading slash with query should strip slash from path
696+ '/path?query=test ' => ['path ' => 'path ' , 'query ' => 'query=test ' ],
697+ // Leading slash with fragment should strip slash from path
698+ '/path#fragment ' => ['path ' => 'path ' , 'fragment ' => 'fragment ' ],
699+ // Only slashes (not root) should be stripped
700+ '// ' => ['path ' => '' ],
701+ '/// ' => ['path ' => '' ],
702+ ];
703+
704+ foreach ($ testCases as $ input => $ expected ) {
705+ $ result = $ method ->invoke ($ this ->resolver , $ input );
706+ $ this ->assertEquals ($ expected , $ result , "Failed for input: ' $ input' " );
707+ }
708+ }
709+
626710 /**
627711 * Test resolve method when finding URL from target path after request path fails
628712 */
0 commit comments