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