Merge "Allow Status::hasMessage to work with Message objects."
[lhc/web/wiklou.git] / tests / phpunit / includes / StatusTest.php
1 <?php
2
3 /**
4 * @author Adam Shorland
5 */
6 class StatusTest extends MediaWikiLangTestCase {
7
8 public function testCanConstruct() {
9 new Status();
10 $this->assertTrue( true );
11 }
12
13 /**
14 * @dataProvider provideValues
15 * @covers Status::newGood
16 */
17 public function testNewGood( $value = null ) {
18 $status = Status::newGood( $value );
19 $this->assertTrue( $status->isGood() );
20 $this->assertTrue( $status->isOK() );
21 $this->assertEquals( $value, $status->getValue() );
22 }
23
24 public static function provideValues() {
25 return array(
26 array(),
27 array( 'foo' ),
28 array( array( 'foo' => 'bar' ) ),
29 array( new Exception() ),
30 array( 1234 ),
31 );
32 }
33
34 /**
35 * @covers Status::newFatal
36 */
37 public function testNewFatalWithMessage() {
38 $message = $this->getMockBuilder( 'Message' )
39 ->disableOriginalConstructor()
40 ->getMock();
41
42 $status = Status::newFatal( $message );
43 $this->assertFalse( $status->isGood() );
44 $this->assertFalse( $status->isOK() );
45 $this->assertEquals( $message, $status->getMessage() );
46 }
47
48 /**
49 * @covers Status::newFatal
50 */
51 public function testNewFatalWithString() {
52 $message = 'foo';
53 $status = Status::newFatal( $message );
54 $this->assertFalse( $status->isGood() );
55 $this->assertFalse( $status->isOK() );
56 $this->assertEquals( $message, $status->getMessage()->getKey() );
57 }
58
59 /**
60 * @dataProvider provideSetResult
61 * @covers Status::setResult
62 */
63 public function testSetResult( $ok, $value = null ) {
64 $status = new Status();
65 $status->setResult( $ok, $value );
66 $this->assertEquals( $ok, $status->isOK() );
67 $this->assertEquals( $value, $status->getValue() );
68 }
69
70 public static function provideSetResult() {
71 return array(
72 array( true ),
73 array( false ),
74 array( true, 'value' ),
75 array( false, 'value' ),
76 );
77 }
78
79 /**
80 * @dataProvider provideIsOk
81 * @covers Status::isOk
82 */
83 public function testIsOk( $ok ) {
84 $status = new Status();
85 $status->ok = $ok;
86 $this->assertEquals( $ok, $status->isOK() );
87 }
88
89 public static function provideIsOk() {
90 return array(
91 array( true ),
92 array( false ),
93 );
94 }
95
96 /**
97 * @covers Status::getValue
98 */
99 public function testGetValue() {
100 $status = new Status();
101 $status->value = 'foobar';
102 $this->assertEquals( 'foobar', $status->getValue() );
103 }
104
105 /**
106 * @dataProvider provideIsGood
107 * @covers Status::isGood
108 */
109 public function testIsGood( $ok, $errors, $expected ) {
110 $status = new Status();
111 $status->ok = $ok;
112 $status->errors = $errors;
113 $this->assertEquals( $expected, $status->isGood() );
114 }
115
116 public static function provideIsGood() {
117 return array(
118 array( true, array(), true ),
119 array( true, array( 'foo' ), false ),
120 array( false, array(), false ),
121 array( false, array( 'foo' ), false ),
122 );
123 }
124
125 /**
126 * @dataProvider provideMockMessageDetails
127 * @covers Status::warning
128 * @covers Status::getWarningsArray
129 * @covers Status::getStatusArray
130 */
131 public function testWarningWithMessage( $mockDetails ) {
132 $status = new Status();
133 $messages = $this->getMockMessages( $mockDetails );
134
135 foreach ( $messages as $message ) {
136 $status->warning( $message );
137 }
138 $warnings = $status->getWarningsArray();
139
140 $this->assertEquals( count( $messages ), count( $warnings ) );
141 foreach ( $messages as $key => $message ) {
142 $expectedArray = array_merge( array( $message->getKey() ), $message->getParams() );
143 $this->assertEquals( $warnings[$key], $expectedArray );
144 }
145 }
146
147 /**
148 * @dataProvider provideMockMessageDetails
149 * @covers Status::error
150 * @covers Status::getErrorsArray
151 * @covers Status::getStatusArray
152 */
153 public function testErrorWithMessage( $mockDetails ) {
154 $status = new Status();
155 $messages = $this->getMockMessages( $mockDetails );
156
157 foreach ( $messages as $message ) {
158 $status->error( $message );
159 }
160 $errors = $status->getErrorsArray();
161
162 $this->assertEquals( count( $messages ), count( $errors ) );
163 foreach ( $messages as $key => $message ) {
164 $expectedArray = array_merge( array( $message->getKey() ), $message->getParams() );
165 $this->assertEquals( $errors[$key], $expectedArray );
166 }
167 }
168
169 /**
170 * @dataProvider provideMockMessageDetails
171 * @covers Status::fatal
172 * @covers Status::getErrorsArray
173 * @covers Status::getStatusArray
174 */
175 public function testFatalWithMessage( $mockDetails ) {
176 $status = new Status();
177 $messages = $this->getMockMessages( $mockDetails );
178
179 foreach ( $messages as $message ) {
180 $status->fatal( $message );
181 }
182 $errors = $status->getErrorsArray();
183
184 $this->assertEquals( count( $messages ), count( $errors ) );
185 foreach ( $messages as $key => $message ) {
186 $expectedArray = array_merge( array( $message->getKey() ), $message->getParams() );
187 $this->assertEquals( $errors[$key], $expectedArray );
188 }
189 $this->assertFalse( $status->isOK() );
190 }
191
192 protected function getMockMessage( $key = 'key', $params = array() ) {
193 $message = $this->getMockBuilder( 'Message' )
194 ->disableOriginalConstructor()
195 ->getMock();
196 $message->expects( $this->atLeastOnce() )
197 ->method( 'getKey' )
198 ->will( $this->returnValue( $key ) );
199 $message->expects( $this->atLeastOnce() )
200 ->method( 'getParams' )
201 ->will( $this->returnValue( $params ) );
202 return $message;
203 }
204
205 /**
206 * @param array $messageDetails eg. array( 'KEY' => array(/PARAMS/) )
207 * @return Message[]
208 */
209 protected function getMockMessages( $messageDetails ) {
210 $messages = array();
211 foreach ( $messageDetails as $key => $paramsArray ) {
212 $messages[] = $this->getMockMessage( $key, $paramsArray );
213 }
214 return $messages;
215 }
216
217 public static function provideMockMessageDetails() {
218 return array(
219 array( array( 'key1' => array( 'foo' => 'bar' ) ) ),
220 array( array( 'key1' => array( 'foo' => 'bar' ), 'key2' => array( 'foo2' => 'bar2' ) ) ),
221 );
222 }
223
224 /**
225 * @covers Status::merge
226 */
227 public function testMerge() {
228 $status1 = new Status();
229 $status2 = new Status();
230 $message1 = $this->getMockMessage( 'warn1' );
231 $message2 = $this->getMockMessage( 'error2' );
232 $status1->warning( $message1 );
233 $status2->error( $message2 );
234
235 $status1->merge( $status2 );
236 $this->assertEquals( 2, count( $status1->getWarningsArray() ) + count( $status1->getErrorsArray() ) );
237 }
238
239 /**
240 * @covers Status::merge
241 */
242 public function testMergeWithOverwriteValue() {
243 $status1 = new Status();
244 $status2 = new Status();
245 $message1 = $this->getMockMessage( 'warn1' );
246 $message2 = $this->getMockMessage( 'error2' );
247 $status1->warning( $message1 );
248 $status2->error( $message2 );
249 $status2->value = 'FooValue';
250
251 $status1->merge( $status2, true );
252 $this->assertEquals( 2, count( $status1->getWarningsArray() ) + count( $status1->getErrorsArray() ) );
253 $this->assertEquals( 'FooValue', $status1->getValue() );
254 }
255
256 /**
257 * @covers Status::hasMessage
258 */
259 public function testHasMessage() {
260 $status = new Status();
261 $status->fatal( 'bad' );
262 $status->fatal( wfMessage( 'bad-msg' ) );
263 $this->assertTrue( $status->hasMessage( 'bad' ) );
264 $this->assertTrue( $status->hasMessage( 'bad-msg' ) );
265 $this->assertTrue( $status->hasMessage( wfMessage( 'bad-msg' ) ) );
266 $this->assertFalse( $status->hasMessage( 'good' ) );
267 }
268
269 /**
270 * @dataProvider provideCleanParams
271 * @covers Status::cleanParams
272 */
273 public function testCleanParams( $cleanCallback, $params, $expected ) {
274 $method = new ReflectionMethod( 'Status', 'cleanParams' );
275 $method->setAccessible( true );
276 $status = new Status();
277 $status->cleanCallback = $cleanCallback;
278
279 $this->assertEquals( $expected, $method->invoke( $status, $params ) );
280 }
281
282 public static function provideCleanParams() {
283 $cleanCallback = function( $value ) {
284 return '-' . $value . '-';
285 };
286
287 return array(
288 array( false, array( 'foo' => 'bar' ), array( 'foo' => 'bar' ) ),
289 array( $cleanCallback, array( 'foo' => 'bar' ), array( 'foo' => '-bar-' ) ),
290 );
291 }
292
293 /**
294 * @dataProvider provideGetWikiTextAndHtml
295 * @covers Status::getWikiText
296 * @todo test long and short context messages generated through this method
297 * this can not really be done now due to use of wfMessage()->plain()
298 * It is possible to mock such methods but only if namespaces are used
299 */
300 public function testGetWikiText( Status $status, $wikitext, $html ) {
301 $this->assertEquals( $wikitext, $status->getWikiText() );
302 }
303
304 /**
305 * @dataProvider provideGetWikiTextAndHtml
306 * @covers Status::getHtml
307 * @todo test long and short context messages generated through this method
308 * this can not really be done now due to use of $this->getWikiText using wfMessage()->plain()
309 * It is possible to mock such methods but only if namespaces are used
310 */
311 public function testGetHtml( Status $status, $wikitext, $html ) {
312 $this->assertEquals( $html, $status->getHTML() );
313 }
314
315 /**
316 * @return array of arrays with values;
317 * 0 => status object
318 * 1 => expected string (with no context)
319 */
320 public static function provideGetWikiTextAndHtml() {
321 $testCases = array();
322
323 $testCases[ 'GoodStatus' ] = array(
324 new Status(),
325 "Internal error: Status::getWikiText called for a good result, this is incorrect\n",
326 "<p>Internal error: Status::getWikiText called for a good result, this is incorrect\n</p>",
327 );
328
329 $status = new Status();
330 $status->ok = false;
331 $testCases[ 'GoodButNoError' ] = array(
332 $status,
333 "Internal error: Status::getWikiText: Invalid result object: no error text but not OK\n",
334 "<p>Internal error: Status::getWikiText: Invalid result object: no error text but not OK\n</p>",
335 );
336
337 $status = new Status();
338 $status->warning( 'fooBar!' );
339 $testCases[ '1StringWarning' ] = array(
340 $status,
341 "<fooBar!>",
342 "<p>&lt;fooBar!&gt;\n</p>",
343 );
344
345 $status = new Status();
346 $status->warning( 'fooBar!' );
347 $status->warning( 'fooBar2!' );
348 $testCases[ '2StringWarnings' ] = array(
349 $status,
350 "* <fooBar!>\n* <fooBar2!>\n",
351 "<ul>\n<li> &lt;fooBar!&gt;\n</li>\n<li> &lt;fooBar2!&gt;\n</li>\n</ul>\n",
352 );
353
354 $status = new Status();
355 $status->warning( new Message( 'fooBar!', array( 'foo', 'bar' ) ) );
356 $testCases[ '1MessageWarning' ] = array(
357 $status,
358 "<fooBar!>",
359 "<p>&lt;fooBar!&gt;\n</p>",
360 );
361
362 $status = new Status();
363 $status->warning( new Message( 'fooBar!', array( 'foo', 'bar' ) ) );
364 $status->warning( new Message( 'fooBar2!' ) );
365 $testCases[ '2MessageWarnings' ] = array(
366 $status,
367 "* <fooBar!>\n* <fooBar2!>\n",
368 "<ul>\n<li> &lt;fooBar!&gt;\n</li>\n<li> &lt;fooBar2!&gt;\n</li>\n</ul>\n",
369 );
370
371 return $testCases;
372 }
373
374 /**
375 * @dataProvider provideGetMessage
376 * @covers Status::getMessage
377 * @todo test long and short context messages generated through this method
378 */
379 public function testGetMessage( Status $status, $expectedParams = array(), $expectedKey ) {
380 $message = $status->getMessage();
381 $this->assertInstanceOf( 'Message', $message );
382 $this->assertEquals( $expectedParams, $message->getParams(), 'Message::getParams' );
383 $this->assertEquals( $expectedKey, $message->getKey(), 'Message::getKey' );
384 }
385
386 /**
387 * @return array of arrays with values;
388 * 0 => status object
389 * 1 => expected Message parameters (with no context)
390 * 2 => expected Message key
391 */
392 public static function provideGetMessage() {
393 $testCases = array();
394
395 $testCases[ 'GoodStatus' ] = array(
396 new Status(),
397 array( "Status::getMessage called for a good result, this is incorrect\n" ),
398 'internalerror_info'
399 );
400
401 $status = new Status();
402 $status->ok = false;
403 $testCases[ 'GoodButNoError' ] = array(
404 $status,
405 array( "Status::getMessage: Invalid result object: no error text but not OK\n" ),
406 'internalerror_info'
407 );
408
409 $status = new Status();
410 $status->warning( 'fooBar!' );
411 $testCases[ '1StringWarning' ] = array(
412 $status,
413 array(),
414 'fooBar!'
415 );
416
417 // FIXME: Assertion tries to compare a StubUserLang with a Language object, because
418 // "data providers are executed before both the call to the setUpBeforeClass static method
419 // and the first call to the setUp method. Because of that you can't access any variables
420 // you create there from within a data provider."
421 // http://phpunit.de/manual/3.7/en/writing-tests-for-phpunit.html
422 // $status = new Status();
423 // $status->warning( 'fooBar!' );
424 // $status->warning( 'fooBar2!' );
425 // $testCases[ '2StringWarnings' ] = array(
426 // $status,
427 // array( new Message( 'fooBar!' ), new Message( 'fooBar2!' ) ),
428 // "* \$1\n* \$2"
429 // );
430
431 $status = new Status();
432 $status->warning( new Message( 'fooBar!', array( 'foo', 'bar' ) ) );
433 $testCases[ '1MessageWarning' ] = array(
434 $status,
435 array( 'foo', 'bar' ),
436 'fooBar!'
437 );
438
439 $status = new Status();
440 $status->warning( new Message( 'fooBar!', array( 'foo', 'bar' ) ) );
441 $status->warning( new Message( 'fooBar2!' ) );
442 $testCases[ '2MessageWarnings' ] = array(
443 $status,
444 array( new Message( 'fooBar!', array( 'foo', 'bar' ) ), new Message( 'fooBar2!' ) ),
445 "* \$1\n* \$2"
446 );
447
448 return $testCases;
449 }
450
451 /**
452 * @covers Status::replaceMessage
453 */
454 public function testReplaceMessage() {
455 $status = new Status();
456 $message = new Message( 'key1', array( 'foo1', 'bar1' ) );
457 $status->error( $message );
458 $newMessage = new Message( 'key2', array( 'foo2', 'bar2' ) );
459
460 $status->replaceMessage( $message, $newMessage );
461
462 $this->assertEquals( $newMessage, $status->errors[0]['message'] );
463 }
464
465 /**
466 * @covers Status::getErrorMessage
467 */
468 public function testGetErrorMessage() {
469 $method = new ReflectionMethod( 'Status', 'getErrorMessage' );
470 $method->setAccessible( true );
471 $status = new Status();
472 $key = 'foo';
473 $params = array( 'bar' );
474
475 /** @var Message $message */
476 $message = $method->invoke( $status, array_merge( array( $key ), $params ) );
477 $this->assertInstanceOf( 'Message', $message );
478 $this->assertEquals( $key, $message->getKey() );
479 $this->assertEquals( $params, $message->getParams() );
480 }
481
482 /**
483 * @covers Status::getErrorMessageArray
484 */
485 public function testGetErrorMessageArray() {
486 $method = new ReflectionMethod( 'Status', 'getErrorMessageArray' );
487 $method->setAccessible( true );
488 $status = new Status();
489 $key = 'foo';
490 $params = array( 'bar' );
491
492 /** @var Message[] $messageArray */
493 $messageArray = $method->invoke(
494 $status,
495 array(
496 array_merge( array( $key ), $params ),
497 array_merge( array( $key ), $params )
498 )
499 );
500
501 $this->assertInternalType( 'array', $messageArray );
502 $this->assertCount( 2, $messageArray );
503 foreach ( $messageArray as $message ) {
504 $this->assertInstanceOf( 'Message', $message );
505 $this->assertEquals( $key, $message->getKey() );
506 $this->assertEquals( $params, $message->getParams() );
507 }
508 }
509
510 /**
511 * @covers Status::getErrorsByType
512 */
513 public function testGetErrorsByType() {
514 $status = new Status();
515 $warning = new Message( 'warning111' );
516 $error = new Message( 'error111' );
517 $status->warning( $warning );
518 $status->error( $error );
519
520 $warnings = $status->getErrorsByType( 'warning' );
521 $errors = $status->getErrorsByType( 'error' );
522
523 $this->assertCount( 1, $warnings );
524 $this->assertCount( 1, $errors );
525 $this->assertEquals( $warning, $warnings[0]['message'] );
526 $this->assertEquals( $error, $errors[0]['message'] );
527 }
528
529 /**
530 * @covers Status::__wakeup
531 */
532 public function testWakeUpSanitizesCallback() {
533 $status = new Status();
534 $status->cleanCallback = function( $value ) {
535 return '-' . $value . '-';
536 };
537 $status->__wakeup();
538 $this->assertEquals( false, $status->cleanCallback );
539 }
540
541 /**
542 * @dataProvider provideNonObjectMessages
543 * @covers Status::getStatusArray
544 */
545 public function testGetStatusArrayWithNonObjectMessages( $nonObjMsg ) {
546 $status = new Status();
547 if ( !array_key_exists( 1, $nonObjMsg ) ) {
548 $status->warning( $nonObjMsg[0] );
549 } else {
550 $status->warning( $nonObjMsg[0], $nonObjMsg[1] );
551 }
552
553 $array = $status->getWarningsArray(); // We use getWarningsArray to access getStatusArray
554
555 $this->assertEquals( 1, count( $array ) );
556 $this->assertEquals( $nonObjMsg, $array[0] );
557 }
558
559 public static function provideNonObjectMessages() {
560 return array(
561 array( array( 'ImaString', array( 'param1' => 'value1' ) ) ),
562 array( array( 'ImaString' ) ),
563 );
564 }
565
566 }