Merge "Warn if stateful ParserOutput transforms are used"
[lhc/web/wiklou.git] / tests / phpunit / includes / parser / ParserOutputTest.php
1 <?php
2
3 use Wikimedia\TestingAccessWrapper;
4
5 /**
6 * @group Database
7 * ^--- trigger DB shadowing because we are using Title magic
8 */
9 class ParserOutputTest extends MediaWikiTestCase {
10
11 public static function provideIsLinkInternal() {
12 return [
13 // Different domains
14 [ false, 'http://example.org', 'http://mediawiki.org' ],
15 // Same domains
16 [ true, 'http://example.org', 'http://example.org' ],
17 [ true, 'https://example.org', 'https://example.org' ],
18 [ true, '//example.org', '//example.org' ],
19 // Same domain different cases
20 [ true, 'http://example.org', 'http://EXAMPLE.ORG' ],
21 // Paths, queries, and fragments are not relevant
22 [ true, 'http://example.org', 'http://example.org/wiki/Main_Page' ],
23 [ true, 'http://example.org', 'http://example.org?my=query' ],
24 [ true, 'http://example.org', 'http://example.org#its-a-fragment' ],
25 // Different protocols
26 [ false, 'http://example.org', 'https://example.org' ],
27 [ false, 'https://example.org', 'http://example.org' ],
28 // Protocol relative servers always match http and https links
29 [ true, '//example.org', 'http://example.org' ],
30 [ true, '//example.org', 'https://example.org' ],
31 // But they don't match strange things like this
32 [ false, '//example.org', 'irc://example.org' ],
33 ];
34 }
35
36 /**
37 * Test to make sure ParserOutput::isLinkInternal behaves properly
38 * @dataProvider provideIsLinkInternal
39 * @covers ParserOutput::isLinkInternal
40 */
41 public function testIsLinkInternal( $shouldMatch, $server, $url ) {
42 $this->assertEquals( $shouldMatch, ParserOutput::isLinkInternal( $server, $url ) );
43 }
44
45 /**
46 * @covers ParserOutput::setExtensionData
47 * @covers ParserOutput::getExtensionData
48 */
49 public function testExtensionData() {
50 $po = new ParserOutput();
51
52 $po->setExtensionData( "one", "Foo" );
53
54 $this->assertEquals( "Foo", $po->getExtensionData( "one" ) );
55 $this->assertNull( $po->getExtensionData( "spam" ) );
56
57 $po->setExtensionData( "two", "Bar" );
58 $this->assertEquals( "Foo", $po->getExtensionData( "one" ) );
59 $this->assertEquals( "Bar", $po->getExtensionData( "two" ) );
60
61 $po->setExtensionData( "one", null );
62 $this->assertNull( $po->getExtensionData( "one" ) );
63 $this->assertEquals( "Bar", $po->getExtensionData( "two" ) );
64 }
65
66 /**
67 * @covers ParserOutput::setProperty
68 * @covers ParserOutput::getProperty
69 * @covers ParserOutput::unsetProperty
70 * @covers ParserOutput::getProperties
71 */
72 public function testProperties() {
73 $po = new ParserOutput();
74
75 $po->setProperty( 'foo', 'val' );
76
77 $properties = $po->getProperties();
78 $this->assertEquals( $po->getProperty( 'foo' ), 'val' );
79 $this->assertEquals( $properties['foo'], 'val' );
80
81 $po->setProperty( 'foo', 'second val' );
82
83 $properties = $po->getProperties();
84 $this->assertEquals( $po->getProperty( 'foo' ), 'second val' );
85 $this->assertEquals( $properties['foo'], 'second val' );
86
87 $po->unsetProperty( 'foo' );
88
89 $properties = $po->getProperties();
90 $this->assertEquals( $po->getProperty( 'foo' ), false );
91 $this->assertArrayNotHasKey( 'foo', $properties );
92 }
93
94 /**
95 * @covers ParserOutput::getText
96 * @dataProvider provideGetText
97 * @param array $options Options to getText()
98 * @param array $poState ParserOptions state fields to set
99 * @param string $text Parser text
100 * @param string $expect Expected output
101 */
102 public function testGetText( $options, $poState, $text, $expect ) {
103 $this->setMwGlobals( [
104 'wgArticlePath' => '/wiki/$1',
105 'wgScriptPath' => '/w',
106 'wgScript' => '/w/index.php',
107 ] );
108 $this->hideDeprecated( 'ParserOutput stateful allowTOC' );
109 $this->hideDeprecated( 'ParserOutput stateful enableSectionEditLinks' );
110
111 $po = new ParserOutput( $text );
112
113 // Emulate Parser
114 $po->setEditSectionTokens( true );
115
116 if ( $poState ) {
117 $wrap = TestingAccessWrapper::newFromObject( $po );
118 foreach ( $poState as $key => $value ) {
119 $wrap->$key = $value;
120 }
121 }
122
123 $actual = $po->getText( $options );
124 $this->assertSame( $expect, $actual );
125 }
126
127 public static function provideGetText() {
128 // phpcs:disable Generic.Files.LineLength
129 $text = <<<EOF
130 <div class="mw-parser-output"><p>Test document.
131 </p>
132 <mw:toc><div id="toc" class="toc"><div class="toctitle"><h2>Contents</h2></div>
133 <ul>
134 <li class="toclevel-1 tocsection-1"><a href="#Section_1"><span class="tocnumber">1</span> <span class="toctext">Section 1</span></a></li>
135 <li class="toclevel-1 tocsection-2"><a href="#Section_2"><span class="tocnumber">2</span> <span class="toctext">Section 2</span></a>
136 <ul>
137 <li class="toclevel-2 tocsection-3"><a href="#Section_2.1"><span class="tocnumber">2.1</span> <span class="toctext">Section 2.1</span></a></li>
138 </ul>
139 </li>
140 <li class="toclevel-1 tocsection-4"><a href="#Section_3"><span class="tocnumber">3</span> <span class="toctext">Section 3</span></a></li>
141 </ul>
142 </div>
143 </mw:toc>
144 <h2><span class="mw-headline" id="Section_1">Section 1</span><mw:editsection page="Test Page" section="1">Section 1</mw:editsection></h2>
145 <p>One
146 </p>
147 <h2><span class="mw-headline" id="Section_2">Section 2</span><mw:editsection page="Test Page" section="2">Section 2</mw:editsection></h2>
148 <p>Two
149 </p>
150 <h3><span class="mw-headline" id="Section_2.1">Section 2.1</span><mw:editsection page="Test Page" section="3">Section 2.1</mw:editsection></h3>
151 <p>Two point one
152 </p>
153 <h2><span class="mw-headline" id="Section_3">Section 3</span><mw:editsection page="Test Page" section="4">Section 3</mw:editsection></h2>
154 <p>Three
155 </p></div>
156 EOF;
157
158 return [
159 'No stateless options, default state' => [
160 [], [], $text, <<<EOF
161 <div class="mw-parser-output"><p>Test document.
162 </p>
163 <div id="toc" class="toc"><div class="toctitle"><h2>Contents</h2></div>
164 <ul>
165 <li class="toclevel-1 tocsection-1"><a href="#Section_1"><span class="tocnumber">1</span> <span class="toctext">Section 1</span></a></li>
166 <li class="toclevel-1 tocsection-2"><a href="#Section_2"><span class="tocnumber">2</span> <span class="toctext">Section 2</span></a>
167 <ul>
168 <li class="toclevel-2 tocsection-3"><a href="#Section_2.1"><span class="tocnumber">2.1</span> <span class="toctext">Section 2.1</span></a></li>
169 </ul>
170 </li>
171 <li class="toclevel-1 tocsection-4"><a href="#Section_3"><span class="tocnumber">3</span> <span class="toctext">Section 3</span></a></li>
172 </ul>
173 </div>
174
175 <h2><span class="mw-headline" id="Section_1">Section 1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&amp;action=edit&amp;section=1" title="Edit section: Section 1">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
176 <p>One
177 </p>
178 <h2><span class="mw-headline" id="Section_2">Section 2</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&amp;action=edit&amp;section=2" title="Edit section: Section 2">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
179 <p>Two
180 </p>
181 <h3><span class="mw-headline" id="Section_2.1">Section 2.1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&amp;action=edit&amp;section=3" title="Edit section: Section 2.1">edit</a><span class="mw-editsection-bracket">]</span></span></h3>
182 <p>Two point one
183 </p>
184 <h2><span class="mw-headline" id="Section_3">Section 3</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&amp;action=edit&amp;section=4" title="Edit section: Section 3">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
185 <p>Three
186 </p></div>
187 EOF
188 ],
189 'No stateless options, TOC statefully disabled' => [
190 [], [ 'mTOCEnabled' => false ], $text, <<<EOF
191 <div class="mw-parser-output"><p>Test document.
192 </p>
193
194 <h2><span class="mw-headline" id="Section_1">Section 1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&amp;action=edit&amp;section=1" title="Edit section: Section 1">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
195 <p>One
196 </p>
197 <h2><span class="mw-headline" id="Section_2">Section 2</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&amp;action=edit&amp;section=2" title="Edit section: Section 2">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
198 <p>Two
199 </p>
200 <h3><span class="mw-headline" id="Section_2.1">Section 2.1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&amp;action=edit&amp;section=3" title="Edit section: Section 2.1">edit</a><span class="mw-editsection-bracket">]</span></span></h3>
201 <p>Two point one
202 </p>
203 <h2><span class="mw-headline" id="Section_3">Section 3</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&amp;action=edit&amp;section=4" title="Edit section: Section 3">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
204 <p>Three
205 </p></div>
206 EOF
207 ],
208 'No stateless options, section edits statefully disabled' => [
209 [], [ 'mEditSectionTokens' => false ], $text, <<<EOF
210 <div class="mw-parser-output"><p>Test document.
211 </p>
212 <div id="toc" class="toc"><div class="toctitle"><h2>Contents</h2></div>
213 <ul>
214 <li class="toclevel-1 tocsection-1"><a href="#Section_1"><span class="tocnumber">1</span> <span class="toctext">Section 1</span></a></li>
215 <li class="toclevel-1 tocsection-2"><a href="#Section_2"><span class="tocnumber">2</span> <span class="toctext">Section 2</span></a>
216 <ul>
217 <li class="toclevel-2 tocsection-3"><a href="#Section_2.1"><span class="tocnumber">2.1</span> <span class="toctext">Section 2.1</span></a></li>
218 </ul>
219 </li>
220 <li class="toclevel-1 tocsection-4"><a href="#Section_3"><span class="tocnumber">3</span> <span class="toctext">Section 3</span></a></li>
221 </ul>
222 </div>
223
224 <h2><span class="mw-headline" id="Section_1">Section 1</span></h2>
225 <p>One
226 </p>
227 <h2><span class="mw-headline" id="Section_2">Section 2</span></h2>
228 <p>Two
229 </p>
230 <h3><span class="mw-headline" id="Section_2.1">Section 2.1</span></h3>
231 <p>Two point one
232 </p>
233 <h2><span class="mw-headline" id="Section_3">Section 3</span></h2>
234 <p>Three
235 </p></div>
236 EOF
237 ],
238 'Stateless options override stateful settings' => [
239 [ 'allowTOC' => true, 'enableSectionEditLinks' => true ],
240 [ 'mTOCEnabled' => false, 'mEditSectionTokens' => false ],
241 $text, <<<EOF
242 <div class="mw-parser-output"><p>Test document.
243 </p>
244 <div id="toc" class="toc"><div class="toctitle"><h2>Contents</h2></div>
245 <ul>
246 <li class="toclevel-1 tocsection-1"><a href="#Section_1"><span class="tocnumber">1</span> <span class="toctext">Section 1</span></a></li>
247 <li class="toclevel-1 tocsection-2"><a href="#Section_2"><span class="tocnumber">2</span> <span class="toctext">Section 2</span></a>
248 <ul>
249 <li class="toclevel-2 tocsection-3"><a href="#Section_2.1"><span class="tocnumber">2.1</span> <span class="toctext">Section 2.1</span></a></li>
250 </ul>
251 </li>
252 <li class="toclevel-1 tocsection-4"><a href="#Section_3"><span class="tocnumber">3</span> <span class="toctext">Section 3</span></a></li>
253 </ul>
254 </div>
255
256 <h2><span class="mw-headline" id="Section_1">Section 1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&amp;action=edit&amp;section=1" title="Edit section: Section 1">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
257 <p>One
258 </p>
259 <h2><span class="mw-headline" id="Section_2">Section 2</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&amp;action=edit&amp;section=2" title="Edit section: Section 2">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
260 <p>Two
261 </p>
262 <h3><span class="mw-headline" id="Section_2.1">Section 2.1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&amp;action=edit&amp;section=3" title="Edit section: Section 2.1">edit</a><span class="mw-editsection-bracket">]</span></span></h3>
263 <p>Two point one
264 </p>
265 <h2><span class="mw-headline" id="Section_3">Section 3</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&amp;action=edit&amp;section=4" title="Edit section: Section 3">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
266 <p>Three
267 </p></div>
268 EOF
269 ],
270 'Statelessly disable section edit links' => [
271 [ 'enableSectionEditLinks' => false ], [], $text, <<<EOF
272 <div class="mw-parser-output"><p>Test document.
273 </p>
274 <div id="toc" class="toc"><div class="toctitle"><h2>Contents</h2></div>
275 <ul>
276 <li class="toclevel-1 tocsection-1"><a href="#Section_1"><span class="tocnumber">1</span> <span class="toctext">Section 1</span></a></li>
277 <li class="toclevel-1 tocsection-2"><a href="#Section_2"><span class="tocnumber">2</span> <span class="toctext">Section 2</span></a>
278 <ul>
279 <li class="toclevel-2 tocsection-3"><a href="#Section_2.1"><span class="tocnumber">2.1</span> <span class="toctext">Section 2.1</span></a></li>
280 </ul>
281 </li>
282 <li class="toclevel-1 tocsection-4"><a href="#Section_3"><span class="tocnumber">3</span> <span class="toctext">Section 3</span></a></li>
283 </ul>
284 </div>
285
286 <h2><span class="mw-headline" id="Section_1">Section 1</span></h2>
287 <p>One
288 </p>
289 <h2><span class="mw-headline" id="Section_2">Section 2</span></h2>
290 <p>Two
291 </p>
292 <h3><span class="mw-headline" id="Section_2.1">Section 2.1</span></h3>
293 <p>Two point one
294 </p>
295 <h2><span class="mw-headline" id="Section_3">Section 3</span></h2>
296 <p>Three
297 </p></div>
298 EOF
299 ],
300 'Statelessly disable TOC' => [
301 [ 'allowTOC' => false ], [], $text, <<<EOF
302 <div class="mw-parser-output"><p>Test document.
303 </p>
304
305 <h2><span class="mw-headline" id="Section_1">Section 1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&amp;action=edit&amp;section=1" title="Edit section: Section 1">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
306 <p>One
307 </p>
308 <h2><span class="mw-headline" id="Section_2">Section 2</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&amp;action=edit&amp;section=2" title="Edit section: Section 2">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
309 <p>Two
310 </p>
311 <h3><span class="mw-headline" id="Section_2.1">Section 2.1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&amp;action=edit&amp;section=3" title="Edit section: Section 2.1">edit</a><span class="mw-editsection-bracket">]</span></span></h3>
312 <p>Two point one
313 </p>
314 <h2><span class="mw-headline" id="Section_3">Section 3</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&amp;action=edit&amp;section=4" title="Edit section: Section 3">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
315 <p>Three
316 </p></div>
317 EOF
318 ],
319 'Statelessly unwrap text' => [
320 [ 'unwrap' => true ], [], $text, <<<EOF
321 <p>Test document.
322 </p>
323 <div id="toc" class="toc"><div class="toctitle"><h2>Contents</h2></div>
324 <ul>
325 <li class="toclevel-1 tocsection-1"><a href="#Section_1"><span class="tocnumber">1</span> <span class="toctext">Section 1</span></a></li>
326 <li class="toclevel-1 tocsection-2"><a href="#Section_2"><span class="tocnumber">2</span> <span class="toctext">Section 2</span></a>
327 <ul>
328 <li class="toclevel-2 tocsection-3"><a href="#Section_2.1"><span class="tocnumber">2.1</span> <span class="toctext">Section 2.1</span></a></li>
329 </ul>
330 </li>
331 <li class="toclevel-1 tocsection-4"><a href="#Section_3"><span class="tocnumber">3</span> <span class="toctext">Section 3</span></a></li>
332 </ul>
333 </div>
334
335 <h2><span class="mw-headline" id="Section_1">Section 1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&amp;action=edit&amp;section=1" title="Edit section: Section 1">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
336 <p>One
337 </p>
338 <h2><span class="mw-headline" id="Section_2">Section 2</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&amp;action=edit&amp;section=2" title="Edit section: Section 2">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
339 <p>Two
340 </p>
341 <h3><span class="mw-headline" id="Section_2.1">Section 2.1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&amp;action=edit&amp;section=3" title="Edit section: Section 2.1">edit</a><span class="mw-editsection-bracket">]</span></span></h3>
342 <p>Two point one
343 </p>
344 <h2><span class="mw-headline" id="Section_3">Section 3</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&amp;action=edit&amp;section=4" title="Edit section: Section 3">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
345 <p>Three
346 </p>
347 EOF
348 ],
349 'Unwrap without a mw-parser-output wrapper' => [
350 [ 'unwrap' => true ], [], '<div class="foobar">Content</div>', '<div class="foobar">Content</div>'
351 ],
352 ];
353 // phpcs:enable
354 }
355
356 }