]> scripts.mit.edu Git - autoinstallsdev/mediawiki.git/blob - tests/phpunit/includes/content/TextContentTest.php
MediaWiki 1.30.2
[autoinstallsdev/mediawiki.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( [
23                         'wgUser' => $user,
24                         'wgTextModelsToParse' => [
25                                 CONTENT_MODEL_WIKITEXT,
26                                 CONTENT_MODEL_CSS,
27                                 CONTENT_MODEL_JAVASCRIPT,
28                         ],
29                         'wgUseTidy' => false,
30                         'wgCapitalLinks' => true,
31                         'wgHooks' => [], // 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 [
48                         [
49                                 'TextContentTest_testGetParserOutput',
50                                 CONTENT_MODEL_TEXT,
51                                 "hello ''world'' & [[stuff]]\n", "hello ''world'' &amp; [[stuff]]",
52                                 [
53                                         'Links' => []
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( [ $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 [
95                         [
96                                 # 0: no signature resolution
97                                 'hello this is ~~~',
98                                 'hello this is ~~~',
99                         ],
100                         [
101                                 # 1: rtrim
102                                 " Foo \n ",
103                                 ' Foo',
104                         ],
105                         [
106                                 # 2: newline normalization
107                                 "LF\n\nCRLF\r\n\r\nCR\r\rEND",
108                                 "LF\n\nCRLF\n\nCR\n\nEND",
109                         ],
110                 ];
111         }
112
113         /**
114          * @dataProvider dataPreSaveTransform
115          * @covers TextContent::preSaveTransform
116          */
117         public function testPreSaveTransform( $text, $expected ) {
118                 global $wgContLang;
119
120                 $options = ParserOptions::newFromUserAndLang( $this->context->getUser(), $wgContLang );
121
122                 $content = $this->newContent( $text );
123                 $content = $content->preSaveTransform(
124                         $this->context->getTitle(),
125                         $this->context->getUser(),
126                         $options
127                 );
128
129                 $this->assertEquals( $expected, $content->getNativeData() );
130         }
131
132         public static function dataPreloadTransform() {
133                 return [
134                         [
135                                 'hello this is ~~~',
136                                 'hello this is ~~~',
137                         ],
138                 ];
139         }
140
141         /**
142          * @dataProvider dataPreloadTransform
143          * @covers TextContent::preloadTransform
144          */
145         public function testPreloadTransform( $text, $expected ) {
146                 global $wgContLang;
147                 $options = ParserOptions::newFromUserAndLang( $this->context->getUser(), $wgContLang );
148
149                 $content = $this->newContent( $text );
150                 $content = $content->preloadTransform( $this->context->getTitle(), $options );
151
152                 $this->assertEquals( $expected, $content->getNativeData() );
153         }
154
155         public static function dataGetRedirectTarget() {
156                 return [
157                         [ '#REDIRECT [[Test]]',
158                                 null,
159                         ],
160                 ];
161         }
162
163         /**
164          * @dataProvider dataGetRedirectTarget
165          * @covers TextContent::getRedirectTarget
166          */
167         public function testGetRedirectTarget( $text, $expected ) {
168                 $content = $this->newContent( $text );
169                 $t = $content->getRedirectTarget();
170
171                 if ( is_null( $expected ) ) {
172                         $this->assertNull( $t, "text should not have generated a redirect target: $text" );
173                 } else {
174                         $this->assertEquals( $expected, $t->getPrefixedText() );
175                 }
176         }
177
178         /**
179          * @dataProvider dataGetRedirectTarget
180          * @covers TextContent::isRedirect
181          */
182         public function testIsRedirect( $text, $expected ) {
183                 $content = $this->newContent( $text );
184
185                 $this->assertEquals( !is_null( $expected ), $content->isRedirect() );
186         }
187
188         public static function dataIsCountable() {
189                 return [
190                         [ '',
191                                 null,
192                                 'any',
193                                 true
194                         ],
195                         [ 'Foo',
196                                 null,
197                                 'any',
198                                 true
199                         ],
200                         [ 'Foo',
201                                 null,
202                                 'comma',
203                                 false
204                         ],
205                         [ 'Foo, bar',
206                                 null,
207                                 'comma',
208                                 false
209                         ],
210                 ];
211         }
212
213         /**
214          * @dataProvider dataIsCountable
215          * @group Database
216          * @covers TextContent::isCountable
217          */
218         public function testIsCountable( $text, $hasLinks, $mode, $expected ) {
219                 $this->setMwGlobals( 'wgArticleCountMethod', $mode );
220
221                 $content = $this->newContent( $text );
222
223                 $v = $content->isCountable( $hasLinks, $this->context->getTitle() );
224
225                 $this->assertEquals(
226                         $expected,
227                         $v,
228                         'isCountable() returned unexpected value ' . var_export( $v, true )
229                                 . ' instead of ' . var_export( $expected, true )
230                                 . " in mode `$mode` for text \"$text\""
231                 );
232         }
233
234         public static function dataGetTextForSummary() {
235                 return [
236                         [ "hello\nworld.",
237                                 16,
238                                 'hello world.',
239                         ],
240                         [ 'hello world.',
241                                 8,
242                                 'hello...',
243                         ],
244                         [ '[[hello world]].',
245                                 8,
246                                 '[[hel...',
247                         ],
248                 ];
249         }
250
251         /**
252          * @dataProvider dataGetTextForSummary
253          * @covers TextContent::getTextForSummary
254          */
255         public function testGetTextForSummary( $text, $maxlength, $expected ) {
256                 $content = $this->newContent( $text );
257
258                 $this->assertEquals( $expected, $content->getTextForSummary( $maxlength ) );
259         }
260
261         /**
262          * @covers TextContent::getTextForSearchIndex
263          */
264         public function testGetTextForSearchIndex() {
265                 $content = $this->newContent( 'hello world.' );
266
267                 $this->assertEquals( 'hello world.', $content->getTextForSearchIndex() );
268         }
269
270         /**
271          * @covers TextContent::copy
272          */
273         public function testCopy() {
274                 $content = $this->newContent( 'hello world.' );
275                 $copy = $content->copy();
276
277                 $this->assertTrue( $content->equals( $copy ), 'copy must be equal to original' );
278                 $this->assertEquals( 'hello world.', $copy->getNativeData() );
279         }
280
281         /**
282          * @covers TextContent::getSize
283          */
284         public function testGetSize() {
285                 $content = $this->newContent( 'hello world.' );
286
287                 $this->assertEquals( 12, $content->getSize() );
288         }
289
290         /**
291          * @covers TextContent::getNativeData
292          */
293         public function testGetNativeData() {
294                 $content = $this->newContent( 'hello world.' );
295
296                 $this->assertEquals( 'hello world.', $content->getNativeData() );
297         }
298
299         /**
300          * @covers TextContent::getWikitextForTransclusion
301          */
302         public function testGetWikitextForTransclusion() {
303                 $content = $this->newContent( 'hello world.' );
304
305                 $this->assertEquals( 'hello world.', $content->getWikitextForTransclusion() );
306         }
307
308         /**
309          * @covers TextContent::getModel
310          */
311         public function testGetModel() {
312                 $content = $this->newContent( "hello world." );
313
314                 $this->assertEquals( CONTENT_MODEL_TEXT, $content->getModel() );
315         }
316
317         /**
318          * @covers TextContent::getContentHandler
319          */
320         public function testGetContentHandler() {
321                 $content = $this->newContent( "hello world." );
322
323                 $this->assertEquals( CONTENT_MODEL_TEXT, $content->getContentHandler()->getModelID() );
324         }
325
326         public static function dataIsEmpty() {
327                 return [
328                         [ '', true ],
329                         [ '  ', false ],
330                         [ '0', false ],
331                         [ 'hallo welt.', false ],
332                 ];
333         }
334
335         /**
336          * @dataProvider dataIsEmpty
337          * @covers TextContent::isEmpty
338          */
339         public function testIsEmpty( $text, $empty ) {
340                 $content = $this->newContent( $text );
341
342                 $this->assertEquals( $empty, $content->isEmpty() );
343         }
344
345         public static function dataEquals() {
346                 return [
347                         [ new TextContent( "hallo" ), null, false ],
348                         [ new TextContent( "hallo" ), new TextContent( "hallo" ), true ],
349                         [ new TextContent( "hallo" ), new JavaScriptContent( "hallo" ), false ],
350                         [ new TextContent( "hallo" ), new WikitextContent( "hallo" ), false ],
351                         [ new TextContent( "hallo" ), new TextContent( "HALLO" ), false ],
352                 ];
353         }
354
355         /**
356          * @dataProvider dataEquals
357          * @covers TextContent::equals
358          */
359         public function testEquals( Content $a, Content $b = null, $equal = false ) {
360                 $this->assertEquals( $equal, $a->equals( $b ) );
361         }
362
363         public static function dataGetDeletionUpdates() {
364                 return [
365                         [ "TextContentTest_testGetSecondaryDataUpdates_1",
366                                 CONTENT_MODEL_TEXT, "hello ''world''\n",
367                                 []
368                         ],
369                         [ "TextContentTest_testGetSecondaryDataUpdates_2",
370                                 CONTENT_MODEL_TEXT, "hello [[world test 21344]]\n",
371                                 []
372                         ],
373                         // TODO: more...?
374                 ];
375         }
376
377         /**
378          * @dataProvider dataGetDeletionUpdates
379          * @covers TextContent::getDeletionUpdates
380          */
381         public function testDeletionUpdates( $title, $model, $text, $expectedStuff ) {
382                 $ns = $this->getDefaultWikitextNS();
383                 $title = Title::newFromText( $title, $ns );
384
385                 $content = ContentHandler::makeContent( $text, $title, $model );
386
387                 $page = WikiPage::factory( $title );
388                 $page->doEditContent( $content, '' );
389
390                 $updates = $content->getDeletionUpdates( $page );
391
392                 // make updates accessible by class name
393                 foreach ( $updates as $update ) {
394                         $class = get_class( $update );
395                         $updates[$class] = $update;
396                 }
397
398                 if ( !$expectedStuff ) {
399                         $this->assertTrue( true ); // make phpunit happy
400                         return;
401                 }
402
403                 foreach ( $expectedStuff as $class => $fieldValues ) {
404                         $this->assertArrayHasKey( $class, $updates, "missing an update of type $class" );
405
406                         $update = $updates[$class];
407
408                         foreach ( $fieldValues as $field => $value ) {
409                                 $v = $update->$field; # if the field doesn't exist, just crash and burn
410                                 $this->assertEquals( $value, $v, "unexpected value for field $field in instance of $class" );
411                         }
412                 }
413
414                 $page->doDeleteArticle( '' );
415         }
416
417         public static function provideConvert() {
418                 return [
419                         [ // #0
420                                 'Hallo Welt',
421                                 CONTENT_MODEL_WIKITEXT,
422                                 'lossless',
423                                 'Hallo Welt'
424                         ],
425                         [ // #1
426                                 'Hallo Welt',
427                                 CONTENT_MODEL_WIKITEXT,
428                                 'lossless',
429                                 'Hallo Welt'
430                         ],
431                         [ // #1
432                                 'Hallo Welt',
433                                 CONTENT_MODEL_CSS,
434                                 'lossless',
435                                 'Hallo Welt'
436                         ],
437                         [ // #1
438                                 'Hallo Welt',
439                                 CONTENT_MODEL_JAVASCRIPT,
440                                 'lossless',
441                                 'Hallo Welt'
442                         ],
443                 ];
444         }
445
446         /**
447          * @dataProvider provideConvert
448          * @covers TextContent::convert
449          */
450         public function testConvert( $text, $model, $lossy, $expectedNative ) {
451                 $content = $this->newContent( $text );
452
453                 $converted = $content->convert( $model, $lossy );
454
455                 if ( $expectedNative === false ) {
456                         $this->assertFalse( $converted, "conversion to $model was expected to fail!" );
457                 } else {
458                         $this->assertInstanceOf( 'Content', $converted );
459                         $this->assertEquals( $expectedNative, $converted->getNativeData() );
460                 }
461         }
462
463         /**
464          * @covers TextContent::normalizeLineEndings
465          * @dataProvider provideNormalizeLineEndings
466          */
467         public function testNormalizeLineEndings( $input, $expected ) {
468                 $this->assertEquals( $expected, TextContent::normalizeLineEndings( $input ) );
469         }
470
471         public static function provideNormalizeLineEndings() {
472                 return [
473                         [
474                                 "Foo\r\nbar",
475                                 "Foo\nbar"
476                         ],
477                         [
478                                 "Foo\rbar",
479                                 "Foo\nbar"
480                         ],
481                         [
482                                 "Foobar\n  ",
483                                 "Foobar"
484                         ]
485                 ];
486         }
487
488 }