Merge "Change MediaWiki UI to use skinStyles so skins can customize"
[lhc/web/wiklou.git] / tests / phpunit / includes / content / WikitextContentTest.php
1 <?php
2
3 /**
4 * @group ContentHandler
5 *
6 * @group Database
7 * ^--- needed, because we do need the database to test link updates
8 */
9 class WikitextContentTest extends TextContentTest {
10 public static $sections = "Intro
11
12 == stuff ==
13 hello world
14
15 == test ==
16 just a test
17
18 == foo ==
19 more stuff
20 ";
21
22 public function newContent( $text ) {
23 return new WikitextContent( $text );
24 }
25
26 public static function dataGetParserOutput() {
27 return array(
28 array(
29 "WikitextContentTest_testGetParserOutput",
30 CONTENT_MODEL_WIKITEXT,
31 "hello ''world''\n",
32 "<p>hello <i>world</i>\n</p>"
33 ),
34 // TODO: more...?
35 );
36 }
37
38 public static function dataGetSecondaryDataUpdates() {
39 return array(
40 array( "WikitextContentTest_testGetSecondaryDataUpdates_1",
41 CONTENT_MODEL_WIKITEXT, "hello ''world''\n",
42 array(
43 'LinksUpdate' => array(
44 'mRecursive' => true,
45 'mLinks' => array()
46 )
47 )
48 ),
49 array( "WikitextContentTest_testGetSecondaryDataUpdates_2",
50 CONTENT_MODEL_WIKITEXT, "hello [[world test 21344]]\n",
51 array(
52 'LinksUpdate' => array(
53 'mRecursive' => true,
54 'mLinks' => array(
55 array( 'World_test_21344' => 0 )
56 )
57 )
58 )
59 ),
60 // TODO: more...?
61 );
62 }
63
64 /**
65 * @dataProvider dataGetSecondaryDataUpdates
66 * @group Database
67 * @covers WikitextContent::getSecondaryDataUpdates
68 */
69 public function testGetSecondaryDataUpdates( $title, $model, $text, $expectedStuff ) {
70 $ns = $this->getDefaultWikitextNS();
71 $title = Title::newFromText( $title, $ns );
72
73 $content = ContentHandler::makeContent( $text, $title, $model );
74
75 $page = WikiPage::factory( $title );
76 $page->doEditContent( $content, '' );
77
78 $updates = $content->getSecondaryDataUpdates( $title );
79
80 // make updates accessible by class name
81 foreach ( $updates as $update ) {
82 $class = get_class( $update );
83 $updates[$class] = $update;
84 }
85
86 foreach ( $expectedStuff as $class => $fieldValues ) {
87 $this->assertArrayHasKey( $class, $updates, "missing an update of type $class" );
88
89 $update = $updates[$class];
90
91 foreach ( $fieldValues as $field => $value ) {
92 $v = $update->$field; #if the field doesn't exist, just crash and burn
93 $this->assertEquals( $value, $v, "unexpected value for field $field in instance of $class" );
94 }
95 }
96
97 $page->doDeleteArticle( '' );
98 }
99
100 public static function dataGetSection() {
101 return array(
102 array( WikitextContentTest::$sections,
103 "0",
104 "Intro"
105 ),
106 array( WikitextContentTest::$sections,
107 "2",
108 "== test ==
109 just a test"
110 ),
111 array( WikitextContentTest::$sections,
112 "8",
113 false
114 ),
115 );
116 }
117
118 /**
119 * @dataProvider dataGetSection
120 * @covers WikitextContent::getSection
121 */
122 public function testGetSection( $text, $sectionId, $expectedText ) {
123 $content = $this->newContent( $text );
124
125 $sectionContent = $content->getSection( $sectionId );
126 if ( is_object( $sectionContent ) ) {
127 $sectionText = $sectionContent->getNativeData();
128 } else {
129 $sectionText = $sectionContent;
130 }
131
132 $this->assertEquals( $expectedText, $sectionText );
133 }
134
135 public static function dataReplaceSection() {
136 return array(
137 array( WikitextContentTest::$sections,
138 "0",
139 "No more",
140 null,
141 trim( preg_replace( '/^Intro/sm', 'No more', WikitextContentTest::$sections ) )
142 ),
143 array( WikitextContentTest::$sections,
144 "",
145 "No more",
146 null,
147 "No more"
148 ),
149 array( WikitextContentTest::$sections,
150 "2",
151 "== TEST ==\nmore fun",
152 null,
153 trim( preg_replace(
154 '/^== test ==.*== foo ==/sm', "== TEST ==\nmore fun\n\n== foo ==",
155 WikitextContentTest::$sections
156 ) )
157 ),
158 array( WikitextContentTest::$sections,
159 "8",
160 "No more",
161 null,
162 WikitextContentTest::$sections
163 ),
164 array( WikitextContentTest::$sections,
165 "new",
166 "No more",
167 "New",
168 trim( WikitextContentTest::$sections ) . "\n\n\n== New ==\n\nNo more"
169 ),
170 );
171 }
172
173 /**
174 * @dataProvider dataReplaceSection
175 * @covers WikitextContent::replaceSection
176 */
177 public function testReplaceSection( $text, $section, $with, $sectionTitle, $expected ) {
178 $content = $this->newContent( $text );
179 $c = $content->replaceSection( $section, $this->newContent( $with ), $sectionTitle );
180
181 $this->assertEquals( $expected, is_null( $c ) ? null : $c->getNativeData() );
182 }
183
184 /**
185 * @covers WikitextContent::addSectionHeader
186 */
187 public function testAddSectionHeader() {
188 $content = $this->newContent( 'hello world' );
189 $content = $content->addSectionHeader( 'test' );
190
191 $this->assertEquals( "== test ==\n\nhello world", $content->getNativeData() );
192 }
193
194 public static function dataPreSaveTransform() {
195 return array(
196 array( 'hello this is ~~~',
197 "hello this is [[Special:Contributions/127.0.0.1|127.0.0.1]]",
198 ),
199 array( 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
200 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
201 ),
202 array( // rtrim
203 " Foo \n ",
204 " Foo",
205 ),
206 );
207 }
208
209 public static function dataPreloadTransform() {
210 return array(
211 array( 'hello this is ~~~',
212 "hello this is ~~~",
213 ),
214 array( 'hello \'\'this\'\' is <noinclude>foo</noinclude><includeonly>bar</includeonly>',
215 'hello \'\'this\'\' is bar',
216 ),
217 );
218 }
219
220 public static function dataGetRedirectTarget() {
221 return array(
222 array( '#REDIRECT [[Test]]',
223 'Test',
224 ),
225 array( '#REDIRECT Test',
226 null,
227 ),
228 array( '* #REDIRECT [[Test]]',
229 null,
230 ),
231 );
232 }
233
234 public static function dataGetTextForSummary() {
235 return array(
236 array( "hello\nworld.",
237 16,
238 'hello world.',
239 ),
240 array( 'hello world.',
241 8,
242 'hello...',
243 ),
244 array( '[[hello world]].',
245 8,
246 'hel...',
247 ),
248 );
249 }
250
251 public static function dataIsCountable() {
252 return array(
253 array( '',
254 null,
255 'any',
256 true
257 ),
258 array( 'Foo',
259 null,
260 'any',
261 true
262 ),
263 array( 'Foo',
264 null,
265 'comma',
266 false
267 ),
268 array( 'Foo, bar',
269 null,
270 'comma',
271 true
272 ),
273 array( 'Foo',
274 null,
275 'link',
276 false
277 ),
278 array( 'Foo [[bar]]',
279 null,
280 'link',
281 true
282 ),
283 array( 'Foo',
284 true,
285 'link',
286 true
287 ),
288 array( 'Foo [[bar]]',
289 false,
290 'link',
291 false
292 ),
293 array( '#REDIRECT [[bar]]',
294 true,
295 'any',
296 false
297 ),
298 array( '#REDIRECT [[bar]]',
299 true,
300 'comma',
301 false
302 ),
303 array( '#REDIRECT [[bar]]',
304 true,
305 'link',
306 false
307 ),
308 );
309 }
310
311 /**
312 * @covers WikitextContent::matchMagicWord
313 */
314 public function testMatchMagicWord() {
315 $mw = MagicWord::get( "staticredirect" );
316
317 $content = $this->newContent( "#REDIRECT [[FOO]]\n__STATICREDIRECT__" );
318 $this->assertTrue( $content->matchMagicWord( $mw ), "should have matched magic word" );
319
320 $content = $this->newContent( "#REDIRECT [[FOO]]" );
321 $this->assertFalse( $content->matchMagicWord( $mw ), "should not have matched magic word" );
322 }
323
324 /**
325 * @covers WikitextContent::updateRedirect
326 */
327 public function testUpdateRedirect() {
328 $target = Title::newFromText( "testUpdateRedirect_target" );
329
330 // test with non-redirect page
331 $content = $this->newContent( "hello world." );
332 $newContent = $content->updateRedirect( $target );
333
334 $this->assertTrue( $content->equals( $newContent ), "content should be unchanged" );
335
336 // test with actual redirect
337 $content = $this->newContent( "#REDIRECT [[Someplace]]" );
338 $newContent = $content->updateRedirect( $target );
339
340 $this->assertFalse( $content->equals( $newContent ), "content should have changed" );
341 $this->assertTrue( $newContent->isRedirect(), "new content should be a redirect" );
342
343 $this->assertEquals( $target->getFullText(), $newContent->getRedirectTarget()->getFullText() );
344 }
345
346 /**
347 * @covers WikitextContent::getModel
348 */
349 public function testGetModel() {
350 $content = $this->newContent( "hello world." );
351
352 $this->assertEquals( CONTENT_MODEL_WIKITEXT, $content->getModel() );
353 }
354
355 /**
356 * @covers WikitextContent::getContentHandler
357 */
358 public function testGetContentHandler() {
359 $content = $this->newContent( "hello world." );
360
361 $this->assertEquals( CONTENT_MODEL_WIKITEXT, $content->getContentHandler()->getModelID() );
362 }
363
364 public function testRedirectParserOption() {
365 $title = Title::newFromText( 'testRedirectParserOption' );
366
367 // Set up hook and its reporting variables
368 $wikitext = null;
369 $redirectTarget = null;
370 $this->mergeMwGlobalArrayValue( 'wgHooks', array(
371 'InternalParseBeforeLinks' => array(
372 function ( &$parser, &$text, &$stripState ) use ( &$wikitext, &$redirectTarget ) {
373 $wikitext = $text;
374 $redirectTarget = $parser->getOptions()->getRedirectTarget();
375 }
376 )
377 ) );
378
379 // Test with non-redirect page
380 $wikitext = false;
381 $redirectTarget = false;
382 $content = $this->newContent( 'hello world.' );
383 $options = $content->getContentHandler()->makeParserOptions( 'canonical' );
384 $options->setRedirectTarget( $title );
385 $content->getParserOutput( $title, null, $options );
386 $this->assertEquals( 'hello world.', $wikitext,
387 'Wikitext passed to hook was not as expected'
388 );
389 $this->assertEquals( null, $redirectTarget, 'Redirect seen in hook was not null' );
390 $this->assertEquals( $title, $options->getRedirectTarget(),
391 'ParserOptions\' redirectTarget was changed'
392 );
393
394 // Test with a redirect page
395 $wikitext = false;
396 $redirectTarget = false;
397 $content = $this->newContent( "#REDIRECT [[TestRedirectParserOption/redir]]\nhello redirect." );
398 $options = $content->getContentHandler()->makeParserOptions( 'canonical' );
399 $content->getParserOutput( $title, null, $options );
400 $this->assertEquals( 'hello redirect.', $wikitext, 'Wikitext passed to hook was not as expected' );
401 $this->assertNotEquals( null, $redirectTarget, 'Redirect seen in hook was null' );
402 $this->assertEquals( 'TestRedirectParserOption/redir', $redirectTarget->getFullText(),
403 'Redirect seen in hook was not the expected title'
404 );
405 $this->assertEquals( null, $options->getRedirectTarget(),
406 'ParserOptions\' redirectTarget was changed'
407 );
408 }
409
410 public static function dataEquals() {
411 return array(
412 array( new WikitextContent( "hallo" ), null, false ),
413 array( new WikitextContent( "hallo" ), new WikitextContent( "hallo" ), true ),
414 array( new WikitextContent( "hallo" ), new JavaScriptContent( "hallo" ), false ),
415 array( new WikitextContent( "hallo" ), new TextContent( "hallo" ), false ),
416 array( new WikitextContent( "hallo" ), new WikitextContent( "HALLO" ), false ),
417 );
418 }
419
420 public static function dataGetDeletionUpdates() {
421 return array(
422 array( "WikitextContentTest_testGetSecondaryDataUpdates_1",
423 CONTENT_MODEL_WIKITEXT, "hello ''world''\n",
424 array( 'LinksDeletionUpdate' => array() )
425 ),
426 array( "WikitextContentTest_testGetSecondaryDataUpdates_2",
427 CONTENT_MODEL_WIKITEXT, "hello [[world test 21344]]\n",
428 array( 'LinksDeletionUpdate' => array() )
429 ),
430 // @todo more...?
431 );
432 }
433 }