Merge "Split down patch-comment-table.sql"
[lhc/web/wiklou.git] / tests / phpunit / unit / includes / language / LanguageFallbackTestTrait.php
1 <?php
2
3 /**
4 * Code to test the getFallbackFor, getFallbacksFor, and getFallbacksIncludingSiteLanguage methods
5 * that have historically been static methods of the Language class. It can be used to test any
6 * class or object that implements those three methods.
7 */
8 trait LanguageFallbackTestTrait {
9 /**
10 * @param array $options Valid keys:
11 * * expectedGets: How many times we expect to hit the localisation cache. (This can be
12 * ignored in integration tests -- it's enough to test in unit tests.)
13 * * siteLangCode
14 * @return string|object Name of class or object with the three methods getFallbackFor,
15 * getFallbacksFor, and getFallbacksIncludingSiteLanguage.
16 */
17 abstract protected function getCallee( array $options = [] );
18
19 /**
20 * @return int Value that was historically in Language::MESSAGES_FALLBACKS
21 */
22 abstract protected function getMessagesKey();
23
24 /**
25 * @return int Value that was historically in Language::STRICT_FALLBACKS
26 */
27 abstract protected function getStrictKey();
28
29 /**
30 * Convenience/readability wrapper to call a method on a class or object.
31 *
32 * @param string|object As in return value of getCallee()
33 * @param string $method Name of method to call
34 * @param mixed ...$params To pass to method
35 * @return mixed Return value of method
36 */
37 private function callMethod( $callee, $method, ...$params ) {
38 return [ $callee, $method ]( ...$params );
39 }
40
41 /**
42 * @param string $code
43 * @param array $expected
44 * @param array $options
45 * @dataProvider provideGetFallbacksFor
46 * @covers ::getFallbackFor
47 * @covers Language::getFallbackFor
48 */
49 public function testGetFallbackFor( $code, array $expected, array $options = [] ) {
50 $callee = $this->getCallee( $options );
51 // One behavior difference between the old static methods and the new instance methods:
52 // returning null instead of false.
53 $defaultExpected = is_object( $callee ) ? null : false;
54 $this->assertSame( $expected[0] ?? $defaultExpected,
55 $this->callMethod( $callee, 'getFallbackFor', $code ) );
56 }
57
58 /**
59 * @param string $code
60 * @param array $expected
61 * @param array $options
62 * @dataProvider provideGetFallbacksFor
63 * @covers ::getFallbacksFor
64 * @covers Language::getFallbacksFor
65 */
66 public function testGetFallbacksFor( $code, array $expected, array $options = [] ) {
67 $this->assertSame( $expected,
68 $this->callMethod( $this->getCallee( $options ), 'getFallbacksFor', $code ) );
69 }
70
71 /**
72 * @param string $code
73 * @param array $expected
74 * @param array $options
75 * @dataProvider provideGetFallbacksFor
76 * @covers ::getFallbacksFor
77 * @covers Language::getFallbacksFor
78 */
79 public function testGetFallbacksFor_messages( $code, array $expected, array $options = [] ) {
80 $this->assertSame( $expected,
81 $this->callMethod( $this->getCallee( $options ), 'getFallbacksFor',
82 $code, $this->getMessagesKey() ) );
83 }
84
85 public static function provideGetFallbacksFor() {
86 return [
87 'en' => [ 'en', [], [ 'expectedGets' => 0 ] ],
88 'fr' => [ 'fr', [ 'en' ] ],
89 'sco' => [ 'sco', [ 'en' ] ],
90 'yi' => [ 'yi', [ 'he', 'en' ] ],
91 'ruq' => [ 'ruq', [ 'ruq-latn', 'ro', 'en' ] ],
92 'sh' => [ 'sh', [ 'bs', 'sr-el', 'hr', 'en' ] ],
93 ];
94 }
95
96 /**
97 * @param string $code
98 * @param array $expected
99 * @param array $options
100 * @dataProvider provideGetFallbacksFor_strict
101 * @covers ::getFallbacksFor
102 * @covers Language::getFallbacksFor
103 */
104 public function testGetFallbacksFor_strict( $code, array $expected, array $options = [] ) {
105 $this->assertSame( $expected,
106 $this->callMethod( $this->getCallee( $options ), 'getFallbacksFor',
107 $code, $this->getStrictKey() ) );
108 }
109
110 public static function provideGetFallbacksFor_strict() {
111 return [
112 'en' => [ 'en', [], [ 'expectedGets' => 0 ] ],
113 'fr' => [ 'fr', [] ],
114 'sco' => [ 'sco', [ 'en' ] ],
115 'yi' => [ 'yi', [ 'he' ] ],
116 'ruq' => [ 'ruq', [ 'ruq-latn', 'ro' ] ],
117 'sh' => [ 'sh', [ 'bs', 'sr-el', 'hr' ] ],
118 ];
119 }
120
121 /**
122 * @covers ::getFallbacksFor
123 * @covers Language::getFallbacksFor
124 */
125 public function testGetFallbacksFor_exception() {
126 $this->setExpectedException( MWException::class, 'Invalid fallback mode "7"' );
127
128 $callee = $this->getCallee( [ 'expectedGets' => 0 ] );
129
130 // These should not throw, because of short-circuiting. If they do, it will fail the test,
131 // because we pass 5 and 6 instead of 7.
132 $this->callMethod( $callee, 'getFallbacksFor', 'en', 5 );
133 $this->callMethod( $callee, 'getFallbacksFor', '!!!', 6 );
134
135 // This is the one that should throw.
136 $this->callMethod( $callee, 'getFallbacksFor', 'fr', 7 );
137 }
138
139 /**
140 * @param string $code
141 * @param string $siteLangCode
142 * @param array $expected
143 * @param int $expectedGets
144 * @dataProvider provideGetFallbacksIncludingSiteLanguage
145 * @covers ::getFallbacksIncludingSiteLanguage
146 * @covers Language::getFallbacksIncludingSiteLanguage
147 */
148 public function testGetFallbacksIncludingSiteLanguage(
149 $code, $siteLangCode, array $expected, $expectedGets = 1
150 ) {
151 $callee = $this->getCallee(
152 [ 'siteLangCode' => $siteLangCode, 'expectedGets' => $expectedGets ] );
153 $this->assertSame( $expected,
154 $this->callMethod( $callee, 'getFallbacksIncludingSiteLanguage', $code ) );
155
156 // Call again to make sure we don't call LocalisationCache again
157 $this->callMethod( $callee, 'getFallbacksIncludingSiteLanguage', $code );
158 }
159
160 public static function provideGetFallbacksIncludingSiteLanguage() {
161 return [
162 'en on en' => [ 'en', 'en', [ [], [ 'en' ] ], 0 ],
163 'fr on en' => [ 'fr', 'en', [ [ 'en' ], [] ] ],
164 'en on fr' => [ 'en', 'fr', [ [], [ 'fr', 'en' ] ] ],
165 'fr on fr' => [ 'fr', 'fr', [ [ 'en' ], [ 'fr' ] ] ],
166
167 'sco on en' => [ 'sco', 'en', [ [ 'en' ], [] ] ],
168 'en on sco' => [ 'en', 'sco', [ [], [ 'sco', 'en' ] ] ],
169 'sco on sco' => [ 'sco', 'sco', [ [ 'en' ], [ 'sco' ] ] ],
170
171 'fr on sco' => [ 'fr', 'sco', [ [ 'en' ], [ 'sco' ] ], 2 ],
172 'sco on fr' => [ 'sco', 'fr', [ [ 'en' ], [ 'fr' ] ], 2 ],
173
174 'fr on yi' => [ 'fr', 'yi', [ [ 'en' ], [ 'yi', 'he' ] ], 2 ],
175 'yi on fr' => [ 'yi', 'fr', [ [ 'he', 'en' ], [ 'fr' ] ], 2 ],
176 'yi on yi' => [ 'yi', 'yi', [ [ 'he', 'en' ], [ 'yi' ] ] ],
177
178 'sh on ruq' => [ 'sh', 'ruq',
179 [ [ 'bs', 'sr-el', 'hr', 'en' ], [ 'ruq', 'ruq-latn', 'ro' ] ], 2 ],
180 'ruq on sh' => [ 'ruq', 'sh',
181 [ [ 'ruq-latn', 'ro', 'en' ], [ 'sh', 'bs', 'sr-el', 'hr' ] ], 2 ],
182 ];
183 }
184 }