MediaWiki
master
|
00001 <?php 00002 00012 class EditPageTest extends MediaWikiTestCase { 00013 00017 function testExtractSectionTitle( $section, $title ) { 00018 $extracted = EditPage::extractSectionTitle( $section ); 00019 $this->assertEquals( $title, $extracted ); 00020 } 00021 00022 public static function provideExtractSectionTitle() { 00023 return array( 00024 array( 00025 "== Test ==\n\nJust a test section.", 00026 "Test" 00027 ), 00028 array( 00029 "An initial section, no header.", 00030 false 00031 ), 00032 array( 00033 "An initial section with a fake heder (bug 32617)\n\n== Test == ??\nwtf", 00034 false 00035 ), 00036 array( 00037 "== Section ==\nfollowed by a fake == Non-section == ??\nnoooo", 00038 "Section" 00039 ), 00040 array( 00041 "== Section== \t\r\n followed by whitespace (bug 35051)", 00042 'Section', 00043 ), 00044 ); 00045 } 00046 00047 protected function forceRevisionDate( WikiPage $page, $timestamp ) { 00048 $dbw = wfGetDB( DB_MASTER ); 00049 00050 $dbw->update( 'revision', 00051 array( 'rev_timestamp' => $timestamp ), 00052 array( 'rev_id' => $page->getLatest() ) ); 00053 00054 $page->clear(); 00055 } 00056 00062 function assertEditedTextEquals( $expected, $actual, $msg='' ) { 00063 return $this->assertEquals( rtrim($expected), rtrim($actual), $msg ); 00064 } 00065 00090 protected function assertEdit( $title, $baseText, $user = null, array $edit, 00091 $expectedCode = EditPage::AS_OK, $expectedText = null, $message = null 00092 ) { 00093 if ( is_string( $title ) ) { 00094 $ns = $this->getDefaultWikitextNS(); 00095 $title = Title::newFromText( $title, $ns ); 00096 } 00097 00098 if ( is_string( $user ) ) { 00099 $user = User::newFromName( $user ); 00100 00101 if ( $user->getId() === 0 ) { 00102 $user->addToDatabase(); 00103 } 00104 } 00105 00106 $page = WikiPage::factory( $title ); 00107 00108 if ( $baseText !== null ) { 00109 $content = ContentHandler::makeContent( $baseText, $title ); 00110 $page->doEditContent( $content, "base text for test" ); 00111 $this->forceRevisionDate( $page, '20120101000000' ); 00112 00113 //sanity check 00114 $page->clear(); 00115 $currentText = ContentHandler::getContentText( $page->getContent() ); 00116 00117 # EditPage rtrim() the user input, so we alter our expected text 00118 # to reflect that. 00119 $this->assertEditedTextEquals( $baseText, $currentText ); 00120 } 00121 00122 if ( $user == null ) { 00123 $user = $GLOBALS['wgUser']; 00124 } else { 00125 $this->setMwGlobals( 'wgUser', $user ); 00126 } 00127 00128 if ( !isset( $edit['wpEditToken'] ) ) { 00129 $edit['wpEditToken'] = $user->getEditToken(); 00130 } 00131 00132 if ( !isset( $edit['wpEdittime'] ) ) { 00133 $edit['wpEdittime'] = $page->exists() ? $page->getTimestamp() : ''; 00134 } 00135 00136 if ( !isset( $edit['wpStarttime'] ) ) { 00137 $edit['wpStarttime'] = wfTimestampNow(); 00138 } 00139 00140 $req = new FauxRequest( $edit, true ); // session ?? 00141 00142 $ep = new EditPage( new Article( $title ) ); 00143 $ep->setContextTitle( $title ); 00144 $ep->importFormData( $req ); 00145 00146 $bot = isset( $edit['bot'] ) ? (bool)$edit['bot'] : false; 00147 00148 // this is where the edit happens! 00149 // Note: don't want to use EditPage::AttemptSave, because it messes with $wgOut 00150 // and throws exceptions like PermissionsError 00151 $status = $ep->internalAttemptSave( $result, $bot ); 00152 00153 if ( $expectedCode !== null ) { 00154 // check edit code 00155 $this->assertEquals( $expectedCode, $status->value, 00156 "Expected result code mismatch. $message" ); 00157 } 00158 00159 $page = WikiPage::factory( $title ); 00160 00161 if ( $expectedText !== null ) { 00162 // check resulting page text 00163 $content = $page->getContent(); 00164 $text = ContentHandler::getContentText( $content ); 00165 00166 # EditPage rtrim() the user input, so we alter our expected text 00167 # to reflect that. 00168 $this->assertEditedTextEquals( $expectedText, $text, 00169 "Expected article text mismatch. $message" ); 00170 } 00171 00172 return $page; 00173 } 00174 00175 public function testCreatePage() { 00176 $text = "Hello World!"; 00177 $edit = array( 00178 'wpTextbox1' => $text, 00179 'wpSummary' => 'just testing', 00180 ); 00181 00182 $this->assertEdit( 'EditPageTest_testCreatePafe', null, null, $edit, 00183 EditPage::AS_SUCCESS_NEW_ARTICLE, $text, 00184 "expected successfull creation with given text" ); 00185 } 00186 00187 public function testUpdatePage() { 00188 $text = "one"; 00189 $edit = array( 00190 'wpTextbox1' => $text, 00191 'wpSummary' => 'first update', 00192 ); 00193 00194 $page = $this->assertEdit( 'EditPageTest_testUpdatePage', "zero", null, $edit, 00195 EditPage::AS_SUCCESS_UPDATE, $text, 00196 "expected successfull update with given text" ); 00197 00198 $this->forceRevisionDate( $page, '20120101000000' ); 00199 00200 $text = "two"; 00201 $edit = array( 00202 'wpTextbox1' => $text, 00203 'wpSummary' => 'second update', 00204 ); 00205 00206 $this->assertEdit( 'EditPageTest_testUpdatePage', null, null, $edit, 00207 EditPage::AS_SUCCESS_UPDATE, $text, 00208 "expected successfull update with given text" ); 00209 } 00210 00211 public static function provideSectionEdit() { 00212 $text = 00213 'Intro 00214 00215 == one == 00216 first section. 00217 00218 == two == 00219 second section. 00220 '; 00221 00222 $sectionOne = 00223 '== one == 00224 hello 00225 '; 00226 00227 $newSection = 00228 '== new section == 00229 00230 hello 00231 '; 00232 00233 $textWithNewSectionOne = preg_replace( '/== one ==.*== two ==/ms', 00234 "$sectionOne\n== two ==", $text ); 00235 00236 $textWithNewSectionAdded = "$text\n$newSection"; 00237 00238 return array( 00239 array( #0 00240 $text, 00241 '', 00242 'hello', 00243 'replace all', 00244 'hello' 00245 ), 00246 00247 array( #1 00248 $text, 00249 '1', 00250 $sectionOne, 00251 'replace first section', 00252 $textWithNewSectionOne, 00253 ), 00254 00255 array( #2 00256 $text, 00257 'new', 00258 'hello', 00259 'new section', 00260 $textWithNewSectionAdded, 00261 ), 00262 ); 00263 } 00264 00268 public function testSectionEdit( $base, $section, $text, $summary, $expected ) { 00269 $edit = array( 00270 'wpTextbox1' => $text, 00271 'wpSummary' => $summary, 00272 'wpSection' => $section, 00273 ); 00274 00275 $this->assertEdit( 'EditPageTest_testSectionEdit', $base, null, $edit, 00276 EditPage::AS_SUCCESS_UPDATE, $expected, 00277 "expected successfull update of section" ); 00278 } 00279 00280 public static function provideAutoMerge() { 00281 $tests = array(); 00282 00283 $tests[] = array( #0: plain conflict 00284 "Elmo", # base edit user 00285 "one\n\ntwo\n\nthree\n", 00286 array( #adam's edit 00287 'wpStarttime' => 1, 00288 'wpTextbox1' => "ONE\n\ntwo\n\nthree\n", 00289 ), 00290 array( #berta's edit 00291 'wpStarttime' => 2, 00292 'wpTextbox1' => "(one)\n\ntwo\n\nthree\n", 00293 ), 00294 EditPage::AS_CONFLICT_DETECTED, # expected code 00295 "ONE\n\ntwo\n\nthree\n", # expected text 00296 'expected edit conflict', # message 00297 ); 00298 00299 $tests[] = array( #1: successful merge 00300 "Elmo", # base edit user 00301 "one\n\ntwo\n\nthree\n", 00302 array( #adam's edit 00303 'wpStarttime' => 1, 00304 'wpTextbox1' => "ONE\n\ntwo\n\nthree\n", 00305 ), 00306 array( #berta's edit 00307 'wpStarttime' => 2, 00308 'wpTextbox1' => "one\n\ntwo\n\nTHREE\n", 00309 ), 00310 EditPage::AS_SUCCESS_UPDATE, # expected code 00311 "ONE\n\ntwo\n\nTHREE\n", # expected text 00312 'expected automatic merge', # message 00313 ); 00314 00315 $text = "Intro\n\n"; 00316 $text .= "== first section ==\n\n"; 00317 $text .= "one\n\ntwo\n\nthree\n\n"; 00318 $text .= "== second section ==\n\n"; 00319 $text .= "four\n\nfive\n\nsix\n\n"; 00320 00321 // extract the first section. 00322 $section = preg_replace( '/.*(== first section ==.*)== second section ==.*/sm', '$1', $text ); 00323 00324 // generate expected text after merge 00325 $expected = str_replace( 'one', 'ONE', str_replace( 'three', 'THREE', $text ) ); 00326 00327 $tests[] = array( #2: merge in section 00328 "Elmo", # base edit user 00329 $text, 00330 array( #adam's edit 00331 'wpStarttime' => 1, 00332 'wpTextbox1' => str_replace( 'one', 'ONE', $section ), 00333 'wpSection' => '1' 00334 ), 00335 array( #berta's edit 00336 'wpStarttime' => 2, 00337 'wpTextbox1' => str_replace( 'three', 'THREE', $section ), 00338 'wpSection' => '1' 00339 ), 00340 EditPage::AS_SUCCESS_UPDATE, # expected code 00341 $expected, # expected text 00342 'expected automatic section merge', # message 00343 ); 00344 00345 // see whether it makes a difference who did the base edit 00346 $testsWithAdam = array_map( function( $test ) { 00347 $test[0] = 'Adam'; // change base edit user 00348 return $test; 00349 }, $tests ); 00350 00351 $testsWithBerta = array_map( function( $test ) { 00352 $test[0] = 'Berta'; // change base edit user 00353 return $test; 00354 }, $tests ); 00355 00356 return array_merge( $tests, $testsWithAdam, $testsWithBerta ); 00357 } 00358 00359 function testHasValidDiff3() { 00360 global $wgDiff3; 00361 00362 if ( !$wgDiff3 ) { 00363 $this->markTestSkipped( "Can't test conflict resolution because \$wgDiff3 is not configured" ); 00364 } elseif ( !file_exists( $wgDiff3 ) ) { 00365 #XXX: this sucks, since it uses arcane internal knowledge about TextContentHandler::merge3 and wfMerge. 00366 $this->markTestSkipped( "Can't test conflict resolution because \$wgDiff3 is misconfigured: can't find $wgDiff3" ); 00367 } 00368 $this->assertTrue( true ); 00369 } 00370 00375 public function testAutoMerge( $baseUser, $text, $adamsEdit, $bertasEdit, 00376 $expectedCode, $expectedText, $message = null 00377 ) { 00378 00379 //create page 00380 $ns = $this->getDefaultWikitextNS(); 00381 $title = Title::newFromText( 'EditPageTest_testAutoMerge', $ns ); 00382 $page = WikiPage::factory( $title ); 00383 00384 if ( $page->exists() ) { 00385 $page->doDeleteArticle( "clean slate for testing" ); 00386 } 00387 00388 $baseEdit = array( 00389 'wpTextbox1' => $text, 00390 ); 00391 00392 $page = $this->assertEdit( 'EditPageTest_testAutoMerge', null, 00393 $baseUser, $baseEdit, null, null, __METHOD__ ); 00394 00395 $this->forceRevisionDate( $page, '20120101000000' ); 00396 00397 $edittime = $page->getTimestamp(); 00398 00399 // start timestamps for conflict detection 00400 if ( !isset( $adamsEdit['wpStarttime'] ) ) { 00401 $adamsEdit['wpStarttime'] = 1; 00402 } 00403 00404 if ( !isset( $bertasEdit['wpStarttime'] ) ) { 00405 $bertasEdit['wpStarttime'] = 2; 00406 } 00407 00408 $starttime = wfTimestampNow(); 00409 $adamsTime = wfTimestamp( TS_MW, (int)wfTimestamp( TS_UNIX, $starttime ) + (int)$adamsEdit['wpStarttime'] ); 00410 $bertasTime = wfTimestamp( TS_MW, (int)wfTimestamp( TS_UNIX, $starttime ) + (int)$bertasEdit['wpStarttime'] ); 00411 00412 $adamsEdit['wpStarttime'] = $adamsTime; 00413 $bertasEdit['wpStarttime'] = $bertasTime; 00414 00415 $adamsEdit['wpSummary'] = 'Adam\'s edit'; 00416 $bertasEdit['wpSummary'] = 'Bertas\'s edit'; 00417 00418 $adamsEdit['wpEdittime'] = $edittime; 00419 $bertasEdit['wpEdittime'] = $edittime; 00420 00421 // first edit 00422 $this->assertEdit( 'EditPageTest_testAutoMerge', null, 'Adam', $adamsEdit, 00423 EditPage::AS_SUCCESS_UPDATE, null, "expected successfull update" ); 00424 00425 // second edit 00426 $this->assertEdit( 'EditPageTest_testAutoMerge', null, 'Berta', $bertasEdit, 00427 $expectedCode, $expectedText, $message ); 00428 } 00429 }