Merge "updater now shows the SQLite file being used"
[lhc/web/wiklou.git] / tests / phpunit / includes / api / ApiEditPageTest.php
1 <?php
2
3 /**
4 * Tests for MediaWiki api.php?action=edit.
5 *
6 * @author Daniel Kinzler
7 *
8 * @group API
9 * @group Database
10 */
11 class ApiEditPageTest extends ApiTestCase {
12
13 public function setup() {
14 global $wgExtraNamespaces, $wgNamespaceContentModels, $wgContentHandlers, $wgContLang;
15
16 parent::setup();
17
18 $wgExtraNamespaces[12312] = 'Dummy';
19 $wgExtraNamespaces[12313] = 'Dummy_talk';
20
21 $wgNamespaceContentModels[12312] = "testing";
22 $wgContentHandlers["testing"] = 'DummyContentHandlerForTesting';
23
24 MWNamespace::getCanonicalNamespaces( true ); # reset namespace cache
25 $wgContLang->resetNamespaces(); # reset namespace cache
26
27 $this->doLogin();
28 }
29
30 public function teardown() {
31 global $wgExtraNamespaces, $wgNamespaceContentModels, $wgContentHandlers, $wgContLang;
32
33 unset( $wgExtraNamespaces[12312] );
34 unset( $wgExtraNamespaces[12313] );
35
36 unset( $wgNamespaceContentModels[12312] );
37 unset( $wgContentHandlers["testing"] );
38
39 MWNamespace::getCanonicalNamespaces( true ); # reset namespace cache
40 $wgContLang->resetNamespaces(); # reset namespace cache
41
42 parent::teardown();
43 }
44
45 function testEdit( ) {
46 $name = 'Help:ApiEditPageTest_testEdit'; // assume Help namespace to default to wikitext
47
48 // -- test new page --------------------------------------------
49 $apiResult = $this->doApiRequestWithToken( array(
50 'action' => 'edit',
51 'title' => $name,
52 'text' => 'some text', ) );
53 $apiResult = $apiResult[0];
54
55 // Validate API result data
56 $this->assertArrayHasKey( 'edit', $apiResult );
57 $this->assertArrayHasKey( 'result', $apiResult['edit'] );
58 $this->assertEquals( 'Success', $apiResult['edit']['result'] );
59
60 $this->assertArrayHasKey( 'new', $apiResult['edit'] );
61 $this->assertArrayNotHasKey( 'nochange', $apiResult['edit'] );
62
63 $this->assertArrayHasKey( 'pageid', $apiResult['edit'] );
64
65 // -- test existing page, no change ----------------------------
66 $data = $this->doApiRequestWithToken( array(
67 'action' => 'edit',
68 'title' => $name,
69 'text' => 'some text', ) );
70
71 $this->assertEquals( 'Success', $data[0]['edit']['result'] );
72
73 $this->assertArrayNotHasKey( 'new', $data[0]['edit'] );
74 $this->assertArrayHasKey( 'nochange', $data[0]['edit'] );
75
76 // -- test existing page, with change --------------------------
77 $data = $this->doApiRequestWithToken( array(
78 'action' => 'edit',
79 'title' => $name,
80 'text' => 'different text' ) );
81
82 $this->assertEquals( 'Success', $data[0]['edit']['result'] );
83
84 $this->assertArrayNotHasKey( 'new', $data[0]['edit'] );
85 $this->assertArrayNotHasKey( 'nochange', $data[0]['edit'] );
86
87 $this->assertArrayHasKey( 'oldrevid', $data[0]['edit'] );
88 $this->assertArrayHasKey( 'newrevid', $data[0]['edit'] );
89 $this->assertNotEquals(
90 $data[0]['edit']['newrevid'],
91 $data[0]['edit']['oldrevid'],
92 "revision id should change after edit"
93 );
94 }
95
96 function testNonTextEdit( ) {
97 $name = 'Dummy:ApiEditPageTest_testNonTextEdit';
98 $data = serialize( 'some bla bla text' );
99
100 // -- test new page --------------------------------------------
101 $apiResult = $this->doApiRequestWithToken( array(
102 'action' => 'edit',
103 'title' => $name,
104 'text' => $data, ) );
105 $apiResult = $apiResult[0];
106
107 // Validate API result data
108 $this->assertArrayHasKey( 'edit', $apiResult );
109 $this->assertArrayHasKey( 'result', $apiResult['edit'] );
110 $this->assertEquals( 'Success', $apiResult['edit']['result'] );
111
112 $this->assertArrayHasKey( 'new', $apiResult['edit'] );
113 $this->assertArrayNotHasKey( 'nochange', $apiResult['edit'] );
114
115 $this->assertArrayHasKey( 'pageid', $apiResult['edit'] );
116
117 // validate resulting revision
118 $page = WikiPage::factory( Title::newFromText( $name ) );
119 $this->assertEquals( "testing", $page->getContentModel() );
120 $this->assertEquals( $data, $page->getContent()->serialize() );
121 }
122
123 static function provideEditAppend() {
124 return array(
125 array( #0: append
126 'foo', 'append', 'bar', "foobar"
127 ),
128 array( #1: prepend
129 'foo', 'prepend', 'bar', "barfoo"
130 ),
131 array( #2: append to empty page
132 '', 'append', 'foo', "foo"
133 ),
134 array( #3: prepend to empty page
135 '', 'prepend', 'foo', "foo"
136 ),
137 array( #4: append to non-existing page
138 null, 'append', 'foo', "foo"
139 ),
140 array( #5: prepend to non-existing page
141 null, 'prepend', 'foo', "foo"
142 ),
143 );
144 }
145
146 /**
147 * @dataProvider provideEditAppend
148 */
149 function testEditAppend( $text, $op, $append, $expected ) {
150 static $count = 0;
151 $count++;
152
153 // assume NS_HELP defaults to wikitext
154 $name = "Help:ApiEditPageTest_testEditAppend_$count";
155
156 // -- create page (or not) -----------------------------------------
157 if ( $text !== null ) {
158 if ( $text === '' ) {
159 // can't create an empty page, so create it with some content
160 list( $re,, ) = $this->doApiRequestWithToken( array(
161 'action' => 'edit',
162 'title' => $name,
163 'text' => '(dummy)', ) );
164 }
165
166 list( $re,, ) = $this->doApiRequestWithToken( array(
167 'action' => 'edit',
168 'title' => $name,
169 'text' => $text, ) );
170
171 $this->assertEquals( 'Success', $re['edit']['result'] ); // sanity
172 }
173
174 // -- try append/prepend --------------------------------------------
175 list( $re,, ) = $this->doApiRequestWithToken( array(
176 'action' => 'edit',
177 'title' => $name,
178 $op . 'text' => $append, ) );
179
180 $this->assertEquals( 'Success', $re['edit']['result'] );
181
182 // -- validate -----------------------------------------------------
183 $page = new WikiPage( Title::newFromText( $name ) );
184 $content = $page->getContent();
185 $this->assertNotNull( $content, 'Page should have been created' );
186
187 $text = $content->getNativeData();
188
189 $this->assertEquals( $expected, $text );
190 }
191
192 function testEditSection() {
193 $this->markTestIncomplete( "not yet implemented" );
194 }
195
196 function testUndo() {
197 $this->markTestIncomplete( "not yet implemented" );
198 }
199
200 function testEditConflict() {
201 static $count = 0;
202 $count++;
203
204 // assume NS_HELP defaults to wikitext
205 $name = "Help:ApiEditPageTest_testEditConflict_$count";
206 $title = Title::newFromText( $name );
207
208 $page = WikiPage::factory( $title );
209
210 // base edit
211 $page->doEditContent( new WikitextContent( "Foo" ),
212 "testing 1", EDIT_NEW, false, self::$users['sysop']->user );
213 $this->forceRevisionDate( $page, '20120101000000' );
214 $baseTime = $page->getRevision()->getTimestamp();
215
216 // conflicting edit
217 $page->doEditContent( new WikitextContent( "Foo bar" ),
218 "testing 2", EDIT_UPDATE, $page->getLatest(), self::$users['uploader']->user );
219 $this->forceRevisionDate( $page, '20120101020202' );
220
221 // try to save edit, expect conflict
222 try {
223 list( $re,, ) = $this->doApiRequestWithToken( array(
224 'action' => 'edit',
225 'title' => $name,
226 'text' => 'nix bar!',
227 'basetimestamp' => $baseTime,
228 ), null, self::$users['sysop']->user );
229
230 $this->fail( 'edit conflict expected' );
231 } catch ( UsageException $ex ) {
232 $this->assertEquals( 'editconflict', $ex->getCodeString() );
233 }
234 }
235
236 function testEditConflict_redirect() {
237 static $count = 0;
238 $count++;
239
240 // assume NS_HELP defaults to wikitext
241 $name = "Help:ApiEditPageTest_testEditConflict_redirect_$count";
242 $title = Title::newFromText( $name );
243 $page = WikiPage::factory( $title );
244
245 $rname = "Help:ApiEditPageTest_testEditConflict_redirect_r$count";
246 $rtitle = Title::newFromText( $rname );
247 $rpage = WikiPage::factory( $rtitle );
248
249 // base edit for content
250 $page->doEditContent( new WikitextContent( "Foo" ),
251 "testing 1", EDIT_NEW, false, self::$users['sysop']->user );
252 $this->forceRevisionDate( $page, '20120101000000' );
253 $baseTime = $page->getRevision()->getTimestamp();
254
255 // base edit for redirect
256 $rpage->doEditContent( new WikitextContent( "#REDIRECT [[$name]]" ),
257 "testing 1", EDIT_NEW, false, self::$users['sysop']->user );
258 $this->forceRevisionDate( $rpage, '20120101000000' );
259
260 // conflicting edit to redirect
261 $rpage->doEditContent( new WikitextContent( "#REDIRECT [[$name]]\n\n[[Category:Test]]" ),
262 "testing 2", EDIT_UPDATE, $page->getLatest(), self::$users['uploader']->user );
263 $this->forceRevisionDate( $rpage, '20120101020202' );
264
265 // try to save edit; should work, because we follow the redirect
266 list( $re,, ) = $this->doApiRequestWithToken( array(
267 'action' => 'edit',
268 'title' => $rname,
269 'text' => 'nix bar!',
270 'basetimestamp' => $baseTime,
271 'redirect' => true,
272 ), null, self::$users['sysop']->user );
273
274 $this->assertEquals( 'Success', $re['edit']['result'],
275 "no edit conflict expected when following redirect" );
276
277 // try again, without following the redirect. Should fail.
278 try {
279 list( $re,, ) = $this->doApiRequestWithToken( array(
280 'action' => 'edit',
281 'title' => $rname,
282 'text' => 'nix bar!',
283 'basetimestamp' => $baseTime,
284 ), null, self::$users['sysop']->user );
285
286 $this->fail( 'edit conflict expected' );
287 } catch ( UsageException $ex ) {
288 $this->assertEquals( 'editconflict', $ex->getCodeString() );
289 }
290 }
291
292 function testEditConflict_bug41990() {
293 static $count = 0;
294 $count++;
295
296 /*
297 * bug 41990: if the target page has a newer revision than the redirect, then editing the
298 * redirect while specifying 'redirect' and *not* specifying 'basetimestamp' erronously
299 * caused an edit conflict to be detected.
300 */
301
302 // assume NS_HELP defaults to wikitext
303 $name = "Help:ApiEditPageTest_testEditConflict_redirect_bug41990_$count";
304 $title = Title::newFromText( $name );
305 $page = WikiPage::factory( $title );
306
307 $rname = "Help:ApiEditPageTest_testEditConflict_redirect_bug41990_r$count";
308 $rtitle = Title::newFromText( $rname );
309 $rpage = WikiPage::factory( $rtitle );
310
311 // base edit for content
312 $page->doEditContent( new WikitextContent( "Foo" ),
313 "testing 1", EDIT_NEW, false, self::$users['sysop']->user );
314 $this->forceRevisionDate( $page, '20120101000000' );
315
316 // base edit for redirect
317 $rpage->doEditContent( new WikitextContent( "#REDIRECT [[$name]]" ),
318 "testing 1", EDIT_NEW, false, self::$users['sysop']->user );
319 $this->forceRevisionDate( $rpage, '20120101000000' );
320 $baseTime = $rpage->getRevision()->getTimestamp();
321
322 // new edit to content
323 $page->doEditContent( new WikitextContent( "Foo bar" ),
324 "testing 2", EDIT_UPDATE, $page->getLatest(), self::$users['uploader']->user );
325 $this->forceRevisionDate( $rpage, '20120101020202' );
326
327 // try to save edit; should work, following the redirect.
328 list( $re,, ) = $this->doApiRequestWithToken( array(
329 'action' => 'edit',
330 'title' => $rname,
331 'text' => 'nix bar!',
332 'redirect' => true,
333 ), null, self::$users['sysop']->user );
334
335 $this->assertEquals( 'Success', $re['edit']['result'],
336 "no edit conflict expected here" );
337 }
338
339 protected function forceRevisionDate( WikiPage $page, $timestamp ) {
340 $dbw = wfGetDB( DB_MASTER );
341
342 $dbw->update( 'revision',
343 array( 'rev_timestamp' => $timestamp ),
344 array( 'rev_id' => $page->getLatest() ) );
345
346 $page->clear();
347 }
348 }