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