@@ -605,12 +605,35 @@ public function testSanitizeTypeHandlesVariousEntityTypes(): void
605
605
public function testParseUrlHandlesVariousUrlFormats (): void
606
606
{
607
607
$ testCases = [
608
+ // Simple URL without leading slash
608
609
'simple-url ' => ['path ' => 'simple-url ' ],
610
+ // URL with leading slash (should be stripped)
609
611
'/leading-slash ' => ['path ' => 'leading-slash ' ],
612
+ // URL with query parameters
610
613
'url-with-query?param=value ' => ['path ' => 'url-with-query ' , 'query ' => 'param=value ' ],
614
+ // Complex path structure
611
615
'complex/path/structure ' => ['path ' => 'complex/path/structure ' ],
616
+ // Root URL (leading slash should be preserved)
612
617
'/ ' => ['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:[email protected] /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 ' ]
614
637
];
615
638
616
639
$ reflection = new \ReflectionClass ($ this ->resolver );
@@ -623,6 +646,67 @@ public function testParseUrlHandlesVariousUrlFormats(): void
623
646
}
624
647
}
625
648
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
+
626
710
/**
627
711
* Test resolve method when finding URL from target path after request path fails
628
712
*/
0 commit comments