Limit test leakage, $wgCapitalLinks expected to be true
[lhc/web/wiklou.git] / tests / phpunit / includes / content / TextContentTest.php
1 <?php
2
3 /**
4 * @group ContentHandler
5 * @group Database
6 * ^--- needed, because we do need the database to test link updates
7 */
8 class TextContentTest extends MediaWikiLangTestCase {
9 protected $context;
10 protected $savedContentGetParserOutput;
11
12 protected function setUp() {
13 global $wgHooks;
14
15 parent::setUp();
16
17 // Anon user
18 $user = new User();
19 $user->setName( '127.0.0.1' );
20
21 $this->context = new RequestContext( new FauxRequest() );
22 $this->context->setTitle( Title::newFromText( 'Test' ) );
23 $this->context->setUser( $user );
24
25 $this->setMwGlobals( array(
26 'wgUser' => $user,
27 'wgTextModelsToParse' => array(
28 CONTENT_MODEL_WIKITEXT,
29 CONTENT_MODEL_CSS,
30 CONTENT_MODEL_JAVASCRIPT,
31 ),
32 'wgUseTidy' => false,
33 'wgAlwaysUseTidy' => false,
34 'wgCapitalLinks' => true,
35 ) );
36
37 // bypass hooks that force custom rendering
38 if ( isset( $wgHooks['ContentGetParserOutput'] ) ) {
39 $this->savedContentGetParserOutput = $wgHooks['ContentGetParserOutput'];
40 unset( $wgHooks['ContentGetParserOutput'] );
41 }
42 }
43
44 public function teardown() {
45 global $wgHooks;
46
47 // restore hooks that force custom rendering
48 if ( $this->savedContentGetParserOutput !== null ) {
49 $wgHooks['ContentGetParserOutput'] = $this->savedContentGetParserOutput;
50 }
51
52 parent::teardown();
53 }
54
55 public function newContent( $text ) {
56 return new TextContent( $text );
57 }
58
59 public static function dataGetParserOutput() {
60 return array(
61 array(
62 'TextContentTest_testGetParserOutput',
63 CONTENT_MODEL_TEXT,
64 "hello ''world'' & [[stuff]]\n", "hello ''world'' &amp; [[stuff]]",
65 array(
66 'Links' => array()
67 )
68 ),
69 // TODO: more...?
70 );
71 }
72
73 /**
74 * @dataProvider dataGetParserOutput
75 * @covers TextContent::getParserOutput
76 */
77 public function testGetParserOutput( $title, $model, $text, $expectedHtml,
78 $expectedFields = null
79 ) {
80 $title = Title::newFromText( $title );
81 $content = ContentHandler::makeContent( $text, $title, $model );
82
83 $po = $content->getParserOutput( $title );
84
85 $html = $po->getText();
86 $html = preg_replace( '#<!--.*?-->#sm', '', $html ); // strip comments
87
88 $this->assertEquals( $expectedHtml, trim( $html ) );
89
90 if ( $expectedFields ) {
91 foreach ( $expectedFields as $field => $exp ) {
92 $f = 'get' . ucfirst( $field );
93 $v = call_user_func( array( $po, $f ) );
94
95 if ( is_array( $exp ) ) {
96 $this->assertArrayEquals( $exp, $v );
97 } else {
98 $this->assertEquals( $exp, $v );
99 }
100 }
101 }
102
103 // TODO: assert more properties
104 }
105
106 public static function dataPreSaveTransform() {
107 return array(
108 array(
109 #0: no signature resolution
110 'hello this is ~~~',
111 'hello this is ~~~',
112 ),
113 array(
114 #1: rtrim
115 " Foo \n ",
116 ' Foo',
117 ),
118 );
119 }
120
121 /**
122 * @dataProvider dataPreSaveTransform
123 * @covers TextContent::preSaveTransform
124 */
125 public function testPreSaveTransform( $text, $expected ) {
126 global $wgContLang;
127
128 $options = ParserOptions::newFromUserAndLang( $this->context->getUser(), $wgContLang );
129
130 $content = $this->newContent( $text );
131 $content = $content->preSaveTransform(
132 $this->context->getTitle(),
133 $this->context->getUser(),
134 $options
135 );
136
137 $this->assertEquals( $expected, $content->getNativeData() );
138 }
139
140 public static function dataPreloadTransform() {
141 return array(
142 array(
143 'hello this is ~~~',
144 'hello this is ~~~',
145 ),
146 );
147 }
148
149 /**
150 * @dataProvider dataPreloadTransform
151 * @covers TextContent::preloadTransform
152 */
153 public function testPreloadTransform( $text, $expected ) {
154 global $wgContLang;
155 $options = ParserOptions::newFromUserAndLang( $this->context->getUser(), $wgContLang );
156
157 $content = $this->newContent( $text );
158 $content = $content->preloadTransform( $this->context->getTitle(), $options );
159
160 $this->assertEquals( $expected, $content->getNativeData() );
161 }
162
163 public static function dataGetRedirectTarget() {
164 return array(
165 array( '#REDIRECT [[Test]]',
166 null,
167 ),
168 );
169 }
170
171 /**
172 * @dataProvider dataGetRedirectTarget
173 * @covers TextContent::getRedirectTarget
174 */
175 public function testGetRedirectTarget( $text, $expected ) {
176 $content = $this->newContent( $text );
177 $t = $content->getRedirectTarget();
178
179 if ( is_null( $expected ) ) {
180 $this->assertNull( $t, "text should not have generated a redirect target: $text" );
181 } else {
182 $this->assertEquals( $expected, $t->getPrefixedText() );
183 }
184 }
185
186 /**
187 * @dataProvider dataGetRedirectTarget
188 * @covers TextContent::isRedirect
189 */
190 public function testIsRedirect( $text, $expected ) {
191 $content = $this->newContent( $text );
192
193 $this->assertEquals( !is_null( $expected ), $content->isRedirect() );
194 }
195
196 /**
197 * @todo Test needs database! Should be done by a test class in the Database group.
198 */
199 /*
200 public function getRedirectChain() {
201 $text = $this->getNativeData();
202 return Title::newFromRedirectArray( $text );
203 }
204 */
205
206 /**
207 * @todo Test needs database! Should be done by a test class in the Database group.
208 */
209 /*
210 public function getUltimateRedirectTarget() {
211 $text = $this->getNativeData();
212 return Title::newFromRedirectRecurse( $text );
213 }
214 */
215
216 public static function dataIsCountable() {
217 return array(
218 array( '',
219 null,
220 'any',
221 true
222 ),
223 array( 'Foo',
224 null,
225 'any',
226 true
227 ),
228 array( 'Foo',
229 null,
230 'comma',
231 false
232 ),
233 array( 'Foo, bar',
234 null,
235 'comma',
236 false
237 ),
238 );
239 }
240
241 /**
242 * @dataProvider dataIsCountable
243 * @group Database
244 * @covers TextContent::isCountable
245 */
246 public function testIsCountable( $text, $hasLinks, $mode, $expected ) {
247 $this->setMwGlobals( 'wgArticleCountMethod', $mode );
248
249 $content = $this->newContent( $text );
250
251 $v = $content->isCountable( $hasLinks, $this->context->getTitle() );
252
253 $this->assertEquals(
254 $expected,
255 $v,
256 'isCountable() returned unexpected value ' . var_export( $v, true )
257 . ' instead of ' . var_export( $expected, true )
258 . " in mode `$mode` for text \"$text\""
259 );
260 }
261
262 public static function dataGetTextForSummary() {
263 return array(
264 array( "hello\nworld.",
265 16,
266 'hello world.',
267 ),
268 array( 'hello world.',
269 8,
270 'hello...',
271 ),
272 array( '[[hello world]].',
273 8,
274 '[[hel...',
275 ),
276 );
277 }
278
279 /**
280 * @dataProvider dataGetTextForSummary
281 * @covers TextContent::getTextForSummary
282 */
283 public function testGetTextForSummary( $text, $maxlength, $expected ) {
284 $content = $this->newContent( $text );
285
286 $this->assertEquals( $expected, $content->getTextForSummary( $maxlength ) );
287 }
288
289 /**
290 * @covers TextContent::getTextForSearchIndex
291 */
292 public function testGetTextForSearchIndex() {
293 $content = $this->newContent( 'hello world.' );
294
295 $this->assertEquals( 'hello world.', $content->getTextForSearchIndex() );
296 }
297
298 /**
299 * @covers TextContent::copy
300 */
301 public function testCopy() {
302 $content = $this->newContent( 'hello world.' );
303 $copy = $content->copy();
304
305 $this->assertTrue( $content->equals( $copy ), 'copy must be equal to original' );
306 $this->assertEquals( 'hello world.', $copy->getNativeData() );
307 }
308
309 /**
310 * @covers TextContent::getSize
311 */
312 public function testGetSize() {
313 $content = $this->newContent( 'hello world.' );
314
315 $this->assertEquals( 12, $content->getSize() );
316 }
317
318 /**
319 * @covers TextContent::getNativeData
320 */
321 public function testGetNativeData() {
322 $content = $this->newContent( 'hello world.' );
323
324 $this->assertEquals( 'hello world.', $content->getNativeData() );
325 }
326
327 /**
328 * @covers TextContent::getWikitextForTransclusion
329 */
330 public function testGetWikitextForTransclusion() {
331 $content = $this->newContent( 'hello world.' );
332
333 $this->assertEquals( 'hello world.', $content->getWikitextForTransclusion() );
334 }
335
336 /**
337 * @covers TextContent::getModel
338 */
339 public function testGetModel() {
340 $content = $this->newContent( "hello world." );
341
342 $this->assertEquals( CONTENT_MODEL_TEXT, $content->getModel() );
343 }
344
345 /**
346 * @covers TextContent::getContentHandler
347 */
348 public function testGetContentHandler() {
349 $content = $this->newContent( "hello world." );
350
351 $this->assertEquals( CONTENT_MODEL_TEXT, $content->getContentHandler()->getModelID() );
352 }
353
354 public static function dataIsEmpty() {
355 return array(
356 array( '', true ),
357 array( ' ', false ),
358 array( '0', false ),
359 array( 'hallo welt.', false ),
360 );
361 }
362
363 /**
364 * @dataProvider dataIsEmpty
365 * @covers TextContent::isEmpty
366 */
367 public function testIsEmpty( $text, $empty ) {
368 $content = $this->newContent( $text );
369
370 $this->assertEquals( $empty, $content->isEmpty() );
371 }
372
373 public static function dataEquals() {
374 return array(
375 array( new TextContent( "hallo" ), null, false ),
376 array( new TextContent( "hallo" ), new TextContent( "hallo" ), true ),
377 array( new TextContent( "hallo" ), new JavaScriptContent( "hallo" ), false ),
378 array( new TextContent( "hallo" ), new WikitextContent( "hallo" ), false ),
379 array( new TextContent( "hallo" ), new TextContent( "HALLO" ), false ),
380 );
381 }
382
383 /**
384 * @dataProvider dataEquals
385 * @covers TextContent::equals
386 */
387 public function testEquals( Content $a, Content $b = null, $equal = false ) {
388 $this->assertEquals( $equal, $a->equals( $b ) );
389 }
390
391 public static function dataGetDeletionUpdates() {
392 return array(
393 array( "TextContentTest_testGetSecondaryDataUpdates_1",
394 CONTENT_MODEL_TEXT, "hello ''world''\n",
395 array()
396 ),
397 array( "TextContentTest_testGetSecondaryDataUpdates_2",
398 CONTENT_MODEL_TEXT, "hello [[world test 21344]]\n",
399 array()
400 ),
401 // TODO: more...?
402 );
403 }
404
405 /**
406 * @dataProvider dataGetDeletionUpdates
407 * @covers TextContent::getDeletionUpdates
408 */
409 public function testDeletionUpdates( $title, $model, $text, $expectedStuff ) {
410 $ns = $this->getDefaultWikitextNS();
411 $title = Title::newFromText( $title, $ns );
412
413 $content = ContentHandler::makeContent( $text, $title, $model );
414
415 $page = WikiPage::factory( $title );
416 $page->doEditContent( $content, '' );
417
418 $updates = $content->getDeletionUpdates( $page );
419
420 // make updates accessible by class name
421 foreach ( $updates as $update ) {
422 $class = get_class( $update );
423 $updates[$class] = $update;
424 }
425
426 if ( !$expectedStuff ) {
427 $this->assertTrue( true ); // make phpunit happy
428 return;
429 }
430
431 foreach ( $expectedStuff as $class => $fieldValues ) {
432 $this->assertArrayHasKey( $class, $updates, "missing an update of type $class" );
433
434 $update = $updates[$class];
435
436 foreach ( $fieldValues as $field => $value ) {
437 $v = $update->$field; #if the field doesn't exist, just crash and burn
438 $this->assertEquals( $value, $v, "unexpected value for field $field in instance of $class" );
439 }
440 }
441
442 $page->doDeleteArticle( '' );
443 }
444
445 public static function provideConvert() {
446 return array(
447 array( // #0
448 'Hallo Welt',
449 CONTENT_MODEL_WIKITEXT,
450 'lossless',
451 'Hallo Welt'
452 ),
453 array( // #1
454 'Hallo Welt',
455 CONTENT_MODEL_WIKITEXT,
456 'lossless',
457 'Hallo Welt'
458 ),
459 array( // #1
460 'Hallo Welt',
461 CONTENT_MODEL_CSS,
462 'lossless',
463 'Hallo Welt'
464 ),
465 array( // #1
466 'Hallo Welt',
467 CONTENT_MODEL_JAVASCRIPT,
468 'lossless',
469 'Hallo Welt'
470 ),
471 );
472 }
473
474 /**
475 * @dataProvider provideConvert
476 * @covers TextContent::convert
477 */
478 public function testConvert( $text, $model, $lossy, $expectedNative ) {
479 $content = $this->newContent( $text );
480
481 $converted = $content->convert( $model, $lossy );
482
483 if ( $expectedNative === false ) {
484 $this->assertFalse( $converted, "conversion to $model was expected to fail!" );
485 } else {
486 $this->assertInstanceOf( 'Content', $converted );
487 $this->assertEquals( $expectedNative, $converted->getNativeData() );
488 }
489 }
490 }