RevisionTest: Make @covers tags absolute
[lhc/web/wiklou.git] / tests / phpunit / includes / StatusTest.php
1 <?php
2
3 /**
4 * @author Addshore
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 [
26 [],
27 [ 'foo' ],
28 [ [ 'foo' => 'bar' ] ],
29 [ new Exception() ],
30 [ 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 * Test 'ok' and 'errors' getters.
61 *
62 * @covers Status::__get
63 */
64 public function testOkAndErrorsGetters() {
65 $status = Status::newGood( 'foo' );
66 $this->assertTrue( $status->ok );
67 $status = Status::newFatal( 'foo', 1, 2 );
68 $this->assertFalse( $status->ok );
69 $this->assertArrayEquals(
70 [
71 [
72 'type' => 'error',
73 'message' => 'foo',
74 'params' => [ 1, 2 ]
75 ]
76 ],
77 $status->errors
78 );
79 }
80
81 /**
82 * Test 'ok' setter.
83 *
84 * @covers Status::__set
85 */
86 public function testOkSetter() {
87 $status = new Status();
88 $status->ok = false;
89 $this->assertFalse( $status->isOK() );
90 $status->ok = true;
91 $this->assertTrue( $status->isOK() );
92 }
93
94 /**
95 * @dataProvider provideSetResult
96 * @covers Status::setResult
97 */
98 public function testSetResult( $ok, $value = null ) {
99 $status = new Status();
100 $status->setResult( $ok, $value );
101 $this->assertEquals( $ok, $status->isOK() );
102 $this->assertEquals( $value, $status->getValue() );
103 }
104
105 public static function provideSetResult() {
106 return [
107 [ true ],
108 [ false ],
109 [ true, 'value' ],
110 [ false, 'value' ],
111 ];
112 }
113
114 /**
115 * @dataProvider provideIsOk
116 * @covers Status::setOK
117 * @covers Status::isOK
118 */
119 public function testIsOk( $ok ) {
120 $status = new Status();
121 $status->setOK( $ok );
122 $this->assertEquals( $ok, $status->isOK() );
123 }
124
125 public static function provideIsOk() {
126 return [
127 [ true ],
128 [ false ],
129 ];
130 }
131
132 /**
133 * @covers Status::getValue
134 */
135 public function testGetValue() {
136 $status = new Status();
137 $status->value = 'foobar';
138 $this->assertEquals( 'foobar', $status->getValue() );
139 }
140
141 /**
142 * @dataProvider provideIsGood
143 * @covers Status::isGood
144 */
145 public function testIsGood( $ok, $errors, $expected ) {
146 $status = new Status();
147 $status->setOK( $ok );
148 foreach ( $errors as $error ) {
149 $status->warning( $error );
150 }
151 $this->assertEquals( $expected, $status->isGood() );
152 }
153
154 public static function provideIsGood() {
155 return [
156 [ true, [], true ],
157 [ true, [ 'foo' ], false ],
158 [ false, [], false ],
159 [ false, [ 'foo' ], false ],
160 ];
161 }
162
163 /**
164 * @dataProvider provideMockMessageDetails
165 * @covers Status::warning
166 * @covers Status::getWarningsArray
167 * @covers Status::getStatusArray
168 */
169 public function testWarningWithMessage( $mockDetails ) {
170 $status = new Status();
171 $messages = $this->getMockMessages( $mockDetails );
172
173 foreach ( $messages as $message ) {
174 $status->warning( $message );
175 }
176 $warnings = $status->getWarningsArray();
177
178 $this->assertEquals( count( $messages ), count( $warnings ) );
179 foreach ( $messages as $key => $message ) {
180 $expectedArray = array_merge( [ $message->getKey() ], $message->getParams() );
181 $this->assertEquals( $warnings[$key], $expectedArray );
182 }
183 }
184
185 /**
186 * @dataProvider provideMockMessageDetails
187 * @covers Status::error
188 * @covers Status::getErrorsArray
189 * @covers Status::getStatusArray
190 * @covers Status::getErrors
191 */
192 public function testErrorWithMessage( $mockDetails ) {
193 $status = new Status();
194 $messages = $this->getMockMessages( $mockDetails );
195
196 foreach ( $messages as $message ) {
197 $status->error( $message );
198 }
199 $errors = $status->getErrorsArray();
200
201 $this->assertEquals( count( $messages ), count( $errors ) );
202 foreach ( $messages as $key => $message ) {
203 $expectedArray = array_merge( [ $message->getKey() ], $message->getParams() );
204 $this->assertEquals( $errors[$key], $expectedArray );
205 }
206 }
207
208 /**
209 * @dataProvider provideMockMessageDetails
210 * @covers Status::fatal
211 * @covers Status::getErrorsArray
212 * @covers Status::getStatusArray
213 */
214 public function testFatalWithMessage( $mockDetails ) {
215 $status = new Status();
216 $messages = $this->getMockMessages( $mockDetails );
217
218 foreach ( $messages as $message ) {
219 $status->fatal( $message );
220 }
221 $errors = $status->getErrorsArray();
222
223 $this->assertEquals( count( $messages ), count( $errors ) );
224 foreach ( $messages as $key => $message ) {
225 $expectedArray = array_merge( [ $message->getKey() ], $message->getParams() );
226 $this->assertEquals( $errors[$key], $expectedArray );
227 }
228 $this->assertFalse( $status->isOK() );
229 }
230
231 protected function getMockMessage( $key = 'key', $params = [] ) {
232 $message = $this->getMockBuilder( 'Message' )
233 ->disableOriginalConstructor()
234 ->getMock();
235 $message->expects( $this->atLeastOnce() )
236 ->method( 'getKey' )
237 ->will( $this->returnValue( $key ) );
238 $message->expects( $this->atLeastOnce() )
239 ->method( 'getParams' )
240 ->will( $this->returnValue( $params ) );
241 return $message;
242 }
243
244 /**
245 * @param array $messageDetails E.g. array( 'KEY' => array(/PARAMS/) )
246 * @return Message[]
247 */
248 protected function getMockMessages( $messageDetails ) {
249 $messages = [];
250 foreach ( $messageDetails as $key => $paramsArray ) {
251 $messages[] = $this->getMockMessage( $key, $paramsArray );
252 }
253 return $messages;
254 }
255
256 public static function provideMockMessageDetails() {
257 return [
258 [ [ 'key1' => [ 'foo' => 'bar' ] ] ],
259 [ [ 'key1' => [ 'foo' => 'bar' ], 'key2' => [ 'foo2' => 'bar2' ] ] ],
260 ];
261 }
262
263 /**
264 * @covers Status::merge
265 */
266 public function testMerge() {
267 $status1 = new Status();
268 $status2 = new Status();
269 $message1 = $this->getMockMessage( 'warn1' );
270 $message2 = $this->getMockMessage( 'error2' );
271 $status1->warning( $message1 );
272 $status2->error( $message2 );
273
274 $status1->merge( $status2 );
275 $this->assertEquals(
276 2,
277 count( $status1->getWarningsArray() ) + count( $status1->getErrorsArray() )
278 );
279 }
280
281 /**
282 * @covers Status::merge
283 */
284 public function testMergeWithOverwriteValue() {
285 $status1 = new Status();
286 $status2 = new Status();
287 $message1 = $this->getMockMessage( 'warn1' );
288 $message2 = $this->getMockMessage( 'error2' );
289 $status1->warning( $message1 );
290 $status2->error( $message2 );
291 $status2->value = 'FooValue';
292
293 $status1->merge( $status2, true );
294 $this->assertEquals(
295 2,
296 count( $status1->getWarningsArray() ) + count( $status1->getErrorsArray() )
297 );
298 $this->assertEquals( 'FooValue', $status1->getValue() );
299 }
300
301 /**
302 * @covers Status::hasMessage
303 */
304 public function testHasMessage() {
305 $status = new Status();
306 $status->fatal( 'bad' );
307 $status->fatal( wfMessage( 'bad-msg' ) );
308 $this->assertTrue( $status->hasMessage( 'bad' ) );
309 $this->assertTrue( $status->hasMessage( 'bad-msg' ) );
310 $this->assertTrue( $status->hasMessage( wfMessage( 'bad-msg' ) ) );
311 $this->assertFalse( $status->hasMessage( 'good' ) );
312 }
313
314 /**
315 * @dataProvider provideCleanParams
316 * @covers Status::cleanParams
317 */
318 public function testCleanParams( $cleanCallback, $params, $expected ) {
319 $method = new ReflectionMethod( 'Status', 'cleanParams' );
320 $method->setAccessible( true );
321 $status = new Status();
322 $status->cleanCallback = $cleanCallback;
323
324 $this->assertEquals( $expected, $method->invoke( $status, $params ) );
325 }
326
327 public static function provideCleanParams() {
328 $cleanCallback = function ( $value ) {
329 return '-' . $value . '-';
330 };
331
332 return [
333 [ false, [ 'foo' => 'bar' ], [ 'foo' => 'bar' ] ],
334 [ $cleanCallback, [ 'foo' => 'bar' ], [ 'foo' => '-bar-' ] ],
335 ];
336 }
337
338 /**
339 * @dataProvider provideGetWikiTextAndHtml
340 * @covers Status::getWikiText
341 */
342 public function testGetWikiText(
343 Status $status, $wikitext, $wrappedWikitext, $html, $wrappedHtml
344 ) {
345 $this->assertEquals( $wikitext, $status->getWikiText() );
346
347 $this->assertEquals( $wrappedWikitext, $status->getWikiText( 'wrap-short', 'wrap-long', 'qqx' ) );
348 }
349
350 /**
351 * @dataProvider provideGetWikiTextAndHtml
352 * @covers Status::getHtml
353 */
354 public function testGetHtml(
355 Status $status, $wikitext, $wrappedWikitext, $html, $wrappedHtml
356 ) {
357 $this->assertEquals( $html, $status->getHTML() );
358
359 $this->assertEquals( $wrappedHtml, $status->getHTML( 'wrap-short', 'wrap-long', 'qqx' ) );
360 }
361
362 /**
363 * @return array Array of arrays with values;
364 * 0 => status object
365 * 1 => expected string (with no context)
366 */
367 public static function provideGetWikiTextAndHtml() {
368 $testCases = [];
369
370 $testCases['GoodStatus'] = [
371 new Status(),
372 "Internal error: Status::getWikiText called for a good result, this is incorrect\n",
373 "(wrap-short: (internalerror_info: Status::getWikiText called for a good result, " .
374 "this is incorrect\n))",
375 "<p>Internal error: Status::getWikiText called for a good result, this is incorrect\n</p>",
376 "<p>(wrap-short: (internalerror_info: Status::getWikiText called for a good result, " .
377 "this is incorrect\n))\n</p>",
378 ];
379
380 $status = new Status();
381 $status->setOK( false );
382 $testCases['GoodButNoError'] = [
383 $status,
384 "Internal error: Status::getWikiText: Invalid result object: no error text but not OK\n",
385 "(wrap-short: (internalerror_info: Status::getWikiText: Invalid result object: " .
386 "no error text but not OK\n))",
387 "<p>Internal error: Status::getWikiText: Invalid result object: no error text but not OK\n</p>",
388 "<p>(wrap-short: (internalerror_info: Status::getWikiText: Invalid result object: " .
389 "no error text but not OK\n))\n</p>",
390 ];
391
392 $status = new Status();
393 $status->warning( 'fooBar!' );
394 $testCases['1StringWarning'] = [
395 $status,
396 "⧼fooBar!⧽",
397 "(wrap-short: (fooBar!))",
398 "<p>⧼fooBar!⧽\n</p>",
399 "<p>(wrap-short: (fooBar!))\n</p>",
400 ];
401
402 $status = new Status();
403 $status->warning( 'fooBar!' );
404 $status->warning( 'fooBar2!' );
405 $testCases['2StringWarnings'] = [
406 $status,
407 "* ⧼fooBar!⧽\n* ⧼fooBar2!⧽\n",
408 "(wrap-long: * (fooBar!)\n* (fooBar2!)\n)",
409 "<ul><li> ⧼fooBar!⧽</li>\n<li> ⧼fooBar2!⧽</li></ul>\n",
410 "<p>(wrap-long: * (fooBar!)\n</p>\n<ul><li> (fooBar2!)</li></ul>\n<p>)\n</p>",
411 ];
412
413 $status = new Status();
414 $status->warning( new Message( 'fooBar!', [ 'foo', 'bar' ] ) );
415 $testCases['1MessageWarning'] = [
416 $status,
417 "⧼fooBar!⧽",
418 "(wrap-short: (fooBar!: foo, bar))",
419 "<p>⧼fooBar!⧽\n</p>",
420 "<p>(wrap-short: (fooBar!: foo, bar))\n</p>",
421 ];
422
423 $status = new Status();
424 $status->warning( new Message( 'fooBar!', [ 'foo', 'bar' ] ) );
425 $status->warning( new Message( 'fooBar2!' ) );
426 $testCases['2MessageWarnings'] = [
427 $status,
428 "* ⧼fooBar!⧽\n* ⧼fooBar2!⧽\n",
429 "(wrap-long: * (fooBar!: foo, bar)\n* (fooBar2!)\n)",
430 "<ul><li> ⧼fooBar!⧽</li>\n<li> ⧼fooBar2!⧽</li></ul>\n",
431 "<p>(wrap-long: * (fooBar!: foo, bar)\n</p>\n<ul><li> (fooBar2!)</li></ul>\n<p>)\n</p>",
432 ];
433
434 return $testCases;
435 }
436
437 private static function sanitizedMessageParams( Message $message ) {
438 return array_map( function ( $p ) {
439 return $p instanceof Message
440 ? [
441 'key' => $p->getKey(),
442 'params' => self::sanitizedMessageParams( $p ),
443 'lang' => $p->getLanguage()->getCode(),
444 ]
445 : $p;
446 }, $message->getParams() );
447 }
448
449 /**
450 * @dataProvider provideGetMessage
451 * @covers Status::getMessage
452 */
453 public function testGetMessage(
454 Status $status, $expectedParams = [], $expectedKey, $expectedWrapper
455 ) {
456 $message = $status->getMessage( null, null, 'qqx' );
457 $this->assertInstanceOf( 'Message', $message );
458 $this->assertEquals( $expectedParams, self::sanitizedMessageParams( $message ),
459 'Message::getParams' );
460 $this->assertEquals( $expectedKey, $message->getKey(), 'Message::getKey' );
461
462 $message = $status->getMessage( 'wrapper-short', 'wrapper-long' );
463 $this->assertInstanceOf( 'Message', $message );
464 $this->assertEquals( $expectedWrapper, $message->getKey(), 'Message::getKey with wrappers' );
465 $this->assertCount( 1, $message->getParams(), 'Message::getParams with wrappers' );
466
467 $message = $status->getMessage( 'wrapper' );
468 $this->assertInstanceOf( 'Message', $message );
469 $this->assertEquals( 'wrapper', $message->getKey(), 'Message::getKey with wrappers' );
470 $this->assertCount( 1, $message->getParams(), 'Message::getParams with wrappers' );
471
472 $message = $status->getMessage( false, 'wrapper' );
473 $this->assertInstanceOf( 'Message', $message );
474 $this->assertEquals( 'wrapper', $message->getKey(), 'Message::getKey with wrappers' );
475 $this->assertCount( 1, $message->getParams(), 'Message::getParams with wrappers' );
476 }
477
478 /**
479 * @return array Array of arrays with values;
480 * 0 => status object
481 * 1 => expected Message parameters (with no context)
482 * 2 => expected Message key
483 */
484 public static function provideGetMessage() {
485 $testCases = [];
486
487 $testCases['GoodStatus'] = [
488 new Status(),
489 [ "Status::getMessage called for a good result, this is incorrect\n" ],
490 'internalerror_info',
491 'wrapper-short'
492 ];
493
494 $status = new Status();
495 $status->setOK( false );
496 $testCases['GoodButNoError'] = [
497 $status,
498 [ "Status::getMessage: Invalid result object: no error text but not OK\n" ],
499 'internalerror_info',
500 'wrapper-short'
501 ];
502
503 $status = new Status();
504 $status->warning( 'fooBar!' );
505 $testCases['1StringWarning'] = [
506 $status,
507 [],
508 'fooBar!',
509 'wrapper-short'
510 ];
511
512 $status = new Status();
513 $status->warning( 'fooBar!' );
514 $status->warning( 'fooBar2!' );
515 $testCases[ '2StringWarnings' ] = [
516 $status,
517 [
518 [ 'key' => 'fooBar!', 'params' => [], 'lang' => 'qqx' ],
519 [ 'key' => 'fooBar2!', 'params' => [], 'lang' => 'qqx' ]
520 ],
521 "* \$1\n* \$2",
522 'wrapper-long'
523 ];
524
525 $status = new Status();
526 $status->warning( new Message( 'fooBar!', [ 'foo', 'bar' ] ) );
527 $testCases['1MessageWarning'] = [
528 $status,
529 [ 'foo', 'bar' ],
530 'fooBar!',
531 'wrapper-short'
532 ];
533
534 $status = new Status();
535 $status->warning( new Message( 'fooBar!', [ 'foo', 'bar' ] ) );
536 $status->warning( new Message( 'fooBar2!' ) );
537 $testCases['2MessageWarnings'] = [
538 $status,
539 [
540 [ 'key' => 'fooBar!', 'params' => [ 'foo', 'bar' ], 'lang' => 'qqx' ],
541 [ 'key' => 'fooBar2!', 'params' => [], 'lang' => 'qqx' ]
542 ],
543 "* \$1\n* \$2",
544 'wrapper-long'
545 ];
546
547 return $testCases;
548 }
549
550 /**
551 * @covers Status::replaceMessage
552 */
553 public function testReplaceMessage() {
554 $status = new Status();
555 $message = new Message( 'key1', [ 'foo1', 'bar1' ] );
556 $status->error( $message );
557 $newMessage = new Message( 'key2', [ 'foo2', 'bar2' ] );
558
559 $status->replaceMessage( $message, $newMessage );
560
561 $this->assertEquals( $newMessage, $status->errors[0]['message'] );
562 }
563
564 /**
565 * @covers Status::getErrorMessage
566 */
567 public function testGetErrorMessage() {
568 $method = new ReflectionMethod( 'Status', 'getErrorMessage' );
569 $method->setAccessible( true );
570 $status = new Status();
571 $key = 'foo';
572 $params = [ 'bar' ];
573
574 /** @var Message $message */
575 $message = $method->invoke( $status, array_merge( [ $key ], $params ) );
576 $this->assertInstanceOf( 'Message', $message );
577 $this->assertEquals( $key, $message->getKey() );
578 $this->assertEquals( $params, $message->getParams() );
579 }
580
581 /**
582 * @covers Status::getErrorMessageArray
583 */
584 public function testGetErrorMessageArray() {
585 $method = new ReflectionMethod( 'Status', 'getErrorMessageArray' );
586 $method->setAccessible( true );
587 $status = new Status();
588 $key = 'foo';
589 $params = [ 'bar' ];
590
591 /** @var Message[] $messageArray */
592 $messageArray = $method->invoke(
593 $status,
594 [
595 array_merge( [ $key ], $params ),
596 array_merge( [ $key ], $params )
597 ]
598 );
599
600 $this->assertInternalType( 'array', $messageArray );
601 $this->assertCount( 2, $messageArray );
602 foreach ( $messageArray as $message ) {
603 $this->assertInstanceOf( 'Message', $message );
604 $this->assertEquals( $key, $message->getKey() );
605 $this->assertEquals( $params, $message->getParams() );
606 }
607 }
608
609 /**
610 * @covers Status::getErrorsByType
611 */
612 public function testGetErrorsByType() {
613 $status = new Status();
614 $warning = new Message( 'warning111' );
615 $error = new Message( 'error111' );
616 $status->warning( $warning );
617 $status->error( $error );
618
619 $warnings = $status->getErrorsByType( 'warning' );
620 $errors = $status->getErrorsByType( 'error' );
621
622 $this->assertCount( 1, $warnings );
623 $this->assertCount( 1, $errors );
624 $this->assertEquals( $warning, $warnings[0]['message'] );
625 $this->assertEquals( $error, $errors[0]['message'] );
626 }
627
628 /**
629 * @covers Status::__wakeup
630 */
631 public function testWakeUpSanitizesCallback() {
632 $status = new Status();
633 $status->cleanCallback = function ( $value ) {
634 return '-' . $value . '-';
635 };
636 $status->__wakeup();
637 $this->assertEquals( false, $status->cleanCallback );
638 }
639
640 /**
641 * @dataProvider provideNonObjectMessages
642 * @covers Status::getStatusArray
643 */
644 public function testGetStatusArrayWithNonObjectMessages( $nonObjMsg ) {
645 $status = new Status();
646 if ( !array_key_exists( 1, $nonObjMsg ) ) {
647 $status->warning( $nonObjMsg[0] );
648 } else {
649 $status->warning( $nonObjMsg[0], $nonObjMsg[1] );
650 }
651
652 $array = $status->getWarningsArray(); // We use getWarningsArray to access getStatusArray
653
654 $this->assertEquals( 1, count( $array ) );
655 $this->assertEquals( $nonObjMsg, $array[0] );
656 }
657
658 public static function provideNonObjectMessages() {
659 return [
660 [ [ 'ImaString', [ 'param1' => 'value1' ] ] ],
661 [ [ 'ImaString' ] ],
662 ];
663 }
664
665 /**
666 * @dataProvider provideErrorsWarningsOnly
667 * @covers Status::splitByErrorType
668 * @covers StatusValue::splitByErrorType
669 */
670 public function testGetErrorsWarningsOnlyStatus( $errorText, $warningText, $type, $errorResult,
671 $warningResult
672 ) {
673 $status = Status::newGood();
674 if ( $errorText ) {
675 $status->fatal( $errorText );
676 }
677 if ( $warningText ) {
678 $status->warning( $warningText );
679 }
680 $testStatus = $status->splitByErrorType()[$type];
681 $this->assertEquals( $errorResult, $testStatus->getErrorsByType( 'error' ) );
682 $this->assertEquals( $warningResult, $testStatus->getErrorsByType( 'warning' ) );
683 }
684
685 public static function provideErrorsWarningsOnly() {
686 return [
687 [
688 'Just an error',
689 'Just a warning',
690 0,
691 [
692 0 => [
693 'type' => 'error',
694 'message' => 'Just an error',
695 'params' => []
696 ],
697 ],
698 [],
699 ], [
700 'Just an error',
701 'Just a warning',
702 1,
703 [],
704 [
705 0 => [
706 'type' => 'warning',
707 'message' => 'Just a warning',
708 'params' => []
709 ],
710 ],
711 ], [
712 null,
713 null,
714 1,
715 [],
716 [],
717 ], [
718 null,
719 null,
720 0,
721 [],
722 [],
723 ]
724 ];
725 }
726
727 }