]> scripts.mit.edu Git - autoinstallsdev/mediawiki.git/blob - tests/phpunit/includes/PathRouterTest.php
MediaWiki 1.30.2-scripts
[autoinstallsdev/mediawiki.git] / tests / phpunit / includes / PathRouterTest.php
1 <?php
2
3 /**
4  * Tests for the PathRouter parsing.
5  *
6  * @covers PathRouter
7  */
8 class PathRouterTest extends MediaWikiTestCase {
9
10         /**
11          * @var PathRouter
12          */
13         protected $basicRouter;
14
15         protected function setUp() {
16                 parent::setUp();
17                 $router = new PathRouter;
18                 $router->add( "/wiki/$1" );
19                 $this->basicRouter = $router;
20         }
21
22         /**
23          * Test basic path parsing
24          */
25         public function testBasic() {
26                 $matches = $this->basicRouter->parse( "/wiki/Foo" );
27                 $this->assertEquals( $matches, [ 'title' => "Foo" ] );
28         }
29
30         /**
31          * Test loose path auto-$1
32          */
33         public function testLoose() {
34                 $router = new PathRouter;
35                 $router->add( "/" ); # Should be the same as "/$1"
36                 $matches = $router->parse( "/Foo" );
37                 $this->assertEquals( $matches, [ 'title' => "Foo" ] );
38
39                 $router = new PathRouter;
40                 $router->add( "/wiki" ); # Should be the same as /wiki/$1
41                 $matches = $router->parse( "/wiki/Foo" );
42                 $this->assertEquals( $matches, [ 'title' => "Foo" ] );
43
44                 $router = new PathRouter;
45                 $router->add( "/wiki/" ); # Should be the same as /wiki/$1
46                 $matches = $router->parse( "/wiki/Foo" );
47                 $this->assertEquals( $matches, [ 'title' => "Foo" ] );
48         }
49
50         /**
51          * Test to ensure that path is based on specifity, not order
52          */
53         public function testOrder() {
54                 $router = new PathRouter;
55                 $router->add( "/$1" );
56                 $router->add( "/a/$1" );
57                 $router->add( "/b/$1" );
58                 $matches = $router->parse( "/a/Foo" );
59                 $this->assertEquals( $matches, [ 'title' => "Foo" ] );
60
61                 $router = new PathRouter;
62                 $router->add( "/b/$1" );
63                 $router->add( "/a/$1" );
64                 $router->add( "/$1" );
65                 $matches = $router->parse( "/a/Foo" );
66                 $this->assertEquals( $matches, [ 'title' => "Foo" ] );
67         }
68
69         /**
70          * Test the handling of key based arrays with a url parameter
71          */
72         public function testKeyParameter() {
73                 $router = new PathRouter;
74                 $router->add( [ 'edit' => "/edit/$1" ], [ 'action' => '$key' ] );
75                 $matches = $router->parse( "/edit/Foo" );
76                 $this->assertEquals( $matches, [ 'title' => "Foo", 'action' => 'edit' ] );
77         }
78
79         /**
80          * Test the handling of $2 inside paths
81          */
82         public function testAdditionalParameter() {
83                 // Basic $2
84                 $router = new PathRouter;
85                 $router->add( '/$2/$1', [ 'test' => '$2' ] );
86                 $matches = $router->parse( "/asdf/Foo" );
87                 $this->assertEquals( $matches, [ 'title' => "Foo", 'test' => 'asdf' ] );
88         }
89
90         /**
91          * Test additional restricted value parameter
92          */
93         public function testRestrictedValue() {
94                 $router = new PathRouter;
95                 $router->add( '/$2/$1',
96                         [ 'test' => '$2' ],
97                         [ '$2' => [ 'a', 'b' ] ]
98                 );
99                 $router->add( '/$2/$1',
100                         [ 'test2' => '$2' ],
101                         [ '$2' => 'c' ]
102                 );
103                 $router->add( '/$1' );
104
105                 $matches = $router->parse( "/asdf/Foo" );
106                 $this->assertEquals( $matches, [ 'title' => "asdf/Foo" ] );
107
108                 $matches = $router->parse( "/a/Foo" );
109                 $this->assertEquals( $matches, [ 'title' => "Foo", 'test' => 'a' ] );
110
111                 $matches = $router->parse( "/c/Foo" );
112                 $this->assertEquals( $matches, [ 'title' => "Foo", 'test2' => 'c' ] );
113         }
114
115         public function callbackForTest( &$matches, $data ) {
116                 $matches['x'] = $data['$1'];
117                 $matches['foo'] = $data['foo'];
118         }
119
120         public function testCallback() {
121                 $router = new PathRouter;
122                 $router->add( "/$1",
123                         [ 'a' => 'b', 'data:foo' => 'bar' ],
124                         [ 'callback' => [ $this, 'callbackForTest' ] ]
125                 );
126                 $matches = $router->parse( '/Foo' );
127                 $this->assertEquals( $matches, [
128                         'title' => "Foo",
129                         'x' => 'Foo',
130                         'a' => 'b',
131                         'foo' => 'bar'
132                 ] );
133         }
134
135         /**
136          * Test to ensure that matches are not made if a parameter expects nonexistent input
137          */
138         public function testFail() {
139                 $router = new PathRouter;
140                 $router->add( "/wiki/$1", [ 'title' => "$1$2" ] );
141                 $matches = $router->parse( "/wiki/A" );
142                 $this->assertEquals( [], $matches );
143         }
144
145         /**
146          * Test to ensure weight of paths is handled correctly
147          */
148         public function testWeight() {
149                 $router = new PathRouter;
150                 $router->addStrict( "/Bar", [ 'ping' => 'pong' ] );
151                 $router->add( "/asdf-$1", [ 'title' => 'qwerty-$1' ] );
152                 $router->add( "/$1" );
153                 $router->add( "/qwerty-$1", [ 'title' => 'asdf-$1' ] );
154                 $router->addStrict( "/Baz", [ 'marco' => 'polo' ] );
155                 $router->add( "/a/$1" );
156                 $router->add( "/asdf/$1" );
157                 $router->add( "/$2/$1", [ 'unrestricted' => '$2' ] );
158                 $router->add( [ 'qwerty' => "/qwerty/$1" ], [ 'qwerty' => '$key' ] );
159                 $router->add( "/$2/$1", [ 'restricted-to-y' => '$2' ], [ '$2' => 'y' ] );
160
161                 foreach (
162                         [
163                                 '/Foo' => [ 'title' => 'Foo' ],
164                                 '/Bar' => [ 'ping' => 'pong' ],
165                                 '/Baz' => [ 'marco' => 'polo' ],
166                                 '/asdf-foo' => [ 'title' => 'qwerty-foo' ],
167                                 '/qwerty-bar' => [ 'title' => 'asdf-bar' ],
168                                 '/a/Foo' => [ 'title' => 'Foo' ],
169                                 '/asdf/Foo' => [ 'title' => 'Foo' ],
170                                 '/qwerty/Foo' => [ 'title' => 'Foo', 'qwerty' => 'qwerty' ],
171                                 '/baz/Foo' => [ 'title' => 'Foo', 'unrestricted' => 'baz' ],
172                                 '/y/Foo' => [ 'title' => 'Foo', 'restricted-to-y' => 'y' ],
173                         ] as $path => $result
174                 ) {
175                         $this->assertEquals( $router->parse( $path ), $result );
176                 }
177         }
178
179         /**
180          * Make sure the router handles titles like Special:Recentchanges correctly
181          */
182         public function testSpecial() {
183                 $matches = $this->basicRouter->parse( "/wiki/Special:Recentchanges" );
184                 $this->assertEquals( $matches, [ 'title' => "Special:Recentchanges" ] );
185         }
186
187         /**
188          * Make sure the router decodes urlencoding properly
189          */
190         public function testUrlencoding() {
191                 $matches = $this->basicRouter->parse( "/wiki/Title_With%20Space" );
192                 $this->assertEquals( $matches, [ 'title' => "Title_With Space" ] );
193         }
194
195         public static function provideRegexpChars() {
196                 return [
197                         [ "$" ],
198                         [ "$1" ],
199                         [ "\\" ],
200                         [ "\\$1" ],
201                 ];
202         }
203
204         /**
205          * Make sure the router doesn't break on special characters like $ used in regexp replacements
206          * @dataProvider provideRegexpChars
207          */
208         public function testRegexpChars( $char ) {
209                 $matches = $this->basicRouter->parse( "/wiki/$char" );
210                 $this->assertEquals( $matches, [ 'title' => "$char" ] );
211         }
212
213         /**
214          * Make sure the router handles characters like +&() properly
215          */
216         public function testCharacters() {
217                 $matches = $this->basicRouter->parse( "/wiki/Plus+And&Dollar\\Stuff();[]{}*" );
218                 $this->assertEquals( $matches, [ 'title' => "Plus+And&Dollar\\Stuff();[]{}*" ] );
219         }
220
221         /**
222          * Make sure the router handles unicode characters correctly
223          * @depends testSpecial
224          * @depends testUrlencoding
225          * @depends testCharacters
226          */
227         public function testUnicode() {
228                 $matches = $this->basicRouter->parse( "/wiki/Spécial:Modifications_récentes" );
229                 $this->assertEquals( $matches, [ 'title' => "Spécial:Modifications_récentes" ] );
230
231                 $matches = $this->basicRouter->parse( "/wiki/Sp%C3%A9cial:Modifications_r%C3%A9centes" );
232                 $this->assertEquals( $matches, [ 'title' => "Spécial:Modifications_récentes" ] );
233         }
234
235         /**
236          * Ensure the router doesn't choke on long paths.
237          */
238         public function testLength() {
239                 // @codingStandardsIgnoreStart Ignore long line warnings
240                 $matches = $this->basicRouter->parse(
241                         "/wiki/Lorem_ipsum_dolor_sit_amet,_consectetur_adipisicing_elit,_sed_do_eiusmod_tempor_incididunt_ut_labore_et_dolore_magna_aliqua._Ut_enim_ad_minim_veniam,_quis_nostrud_exercitation_ullamco_laboris_nisi_ut_aliquip_ex_ea_commodo_consequat._Duis_aute_irure_dolor_in_reprehenderit_in_voluptate_velit_esse_cillum_dolore_eu_fugiat_nulla_pariatur._Excepteur_sint_occaecat_cupidatat_non_proident,_sunt_in_culpa_qui_officia_deserunt_mollit_anim_id_est_laborum."
242                 );
243                 $this->assertEquals(
244                         $matches,
245                         [ 'title' => "Lorem_ipsum_dolor_sit_amet,_consectetur_adipisicing_elit,_sed_do_eiusmod_tempor_incididunt_ut_labore_et_dolore_magna_aliqua._Ut_enim_ad_minim_veniam,_quis_nostrud_exercitation_ullamco_laboris_nisi_ut_aliquip_ex_ea_commodo_consequat._Duis_aute_irure_dolor_in_reprehenderit_in_voluptate_velit_esse_cillum_dolore_eu_fugiat_nulla_pariatur._Excepteur_sint_occaecat_cupidatat_non_proident,_sunt_in_culpa_qui_officia_deserunt_mollit_anim_id_est_laborum." ]
246                 );
247                 // @codingStandardsIgnoreEnd
248         }
249
250         /**
251          * Ensure that the php passed site of parameter values are not urldecoded
252          */
253         public function testPatternUrlencoding() {
254                 $router = new PathRouter;
255                 $router->add( "/wiki/$1", [ 'title' => '%20:$1' ] );
256                 $matches = $router->parse( "/wiki/Foo" );
257                 $this->assertEquals( $matches, [ 'title' => '%20:Foo' ] );
258         }
259
260         /**
261          * Ensure that raw parameter values do not have any variable replacements or urldecoding
262          */
263         public function testRawParamValue() {
264                 $router = new PathRouter;
265                 $router->add( "/wiki/$1", [ 'title' => [ 'value' => 'bar%20$1' ] ] );
266                 $matches = $router->parse( "/wiki/Foo" );
267                 $this->assertEquals( $matches, [ 'title' => 'bar%20$1' ] );
268         }
269 }