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