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