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