1<?php 2 3namespace dokuwiki\plugin\struct\test\action; 4 5use dokuwiki\plugin\struct\meta; 6use dokuwiki\plugin\struct\test\mock\action_plugin_struct_edit; 7use dokuwiki\plugin\struct\test\mock\Assignments; 8use dokuwiki\plugin\struct\test\StructTest; 9use DOMWrap\Document; 10 11/** 12 * @group plugin_struct 13 * @group plugins 14 * 15 * @covers action_plugin_struct_revert 16 * @covers action_plugin_struct_edit 17 */ 18class EditTest extends StructTest 19{ 20 21 public function setUp(): void 22 { 23 parent::setUp(); 24 25 $this->loadSchemaJSON('schema1'); 26 $this->loadSchemaJSON('schema2', 'schema2int'); 27 $this->saveData( 28 'page01', 29 'schema1', 30 [ 31 'first' => 'first data', 32 'second' => ['second data', 'more data', 'even more'], 33 'third' => 'third data', 34 'fourth' => 'fourth data' 35 ], 36 time() 37 ); 38 } 39 40 /** 41 * Check if a field has the correct value 42 * 43 * @param Document $pq 44 * @param string $schema 45 * @param string $name 46 * @param string $value 47 */ 48 protected function checkField(Document $pq, $schema, $name, $value) 49 { 50 $this->assertEquals( 51 1, 52 $pq->find("span.label:contains('$name')")->count(), 53 "Field $schema.$name not found" 54 ); 55 $this->assertEquals( 56 $value, 57 $pq->find("input[name='struct_schema_data[$schema][$name]']")->attr('value'), 58 "Field $schema.$name has wrong value" 59 ); 60 } 61 62 public function test_createForm_storedData() 63 { 64 $edit = new action_plugin_struct_edit(); 65 global $ID; 66 $ID = 'page01'; 67 $test_html = $edit->createForm('schema1'); 68 69 $doc = new Document(); 70 $doc->loadHTML($test_html); 71 $this->assertEquals('schema1', $doc->find('legend')->text()); 72 $this->checkField($doc, 'schema1', 'first', 'first data'); 73 $this->checkField($doc, 'schema1', 'second', 'second data, more data, even more'); 74 $this->checkField($doc, 'schema1', 'third', 'third data'); 75 $this->checkField($doc, 'schema1', 'fourth', 'fourth data'); 76 } 77 78 public function test_createForm_emptyData() 79 { 80 $edit = new action_plugin_struct_edit(); 81 global $ID; 82 $ID = 'page02'; 83 $test_html = $edit->createForm('schema1'); 84 85 $doc = new Document(); 86 $doc->loadHTML($test_html); 87 $this->assertEquals('schema1', $doc->find('legend')->text()); 88 $this->checkField($doc, 'schema1', 'first', ''); 89 $this->checkField($doc, 'schema1', 'second', ''); 90 $this->checkField($doc, 'schema1', 'third', ''); 91 $this->checkField($doc, 'schema1', 'fourth', ''); 92 } 93 94 public function test_createForm_postData() 95 { 96 global $INPUT, $ID; 97 $ID = 'page01'; 98 $structdata = [ 99 'schema1' => [ 100 'first' => 'first post data', 101 'second' => ['second post data', 'more post data', 'even more post data'], 102 'third' => 'third post data', 103 'fourth' => 'fourth post data' 104 ] 105 ]; 106 $INPUT->set(action_plugin_struct_edit::getVAR(), $structdata); 107 108 $edit = new action_plugin_struct_edit(); 109 $test_html = $edit->createForm('schema1'); 110 111 $doc = new Document(); 112 $doc->loadHTML($test_html); 113 $this->assertEquals('schema1', $doc->find('legend')->text()); 114 $this->checkField($doc, 'schema1', 'first', 'first post data'); 115 $this->checkField($doc, 'schema1', 'second', 'second post data, more post data, even more post data'); 116 $this->checkField($doc, 'schema1', 'third', 'third post data'); 117 $this->checkField($doc, 'schema1', 'fourth', 'fourth post data'); 118 } 119 120 public function test_edit_page_wo_schema() 121 { 122 $page = 'test_edit_page_wo_schema'; 123 124 $request = new \TestRequest(); 125 $response = $request->get(['id' => $page, 'do' => 'edit'], '/doku.php'); 126 $structElement = $response->queryHTML('.struct_entry_form'); 127 128 $this->assertCount(1, $structElement); 129 $this->assertEquals($structElement->html(), ''); 130 } 131 132 public function test_edit_page_with_schema() 133 { 134 $page = 'test_edit_page_with_schema'; 135 $assignment = Assignments::getInstance(); 136 $schema = 'schema2'; 137 $assignment->addPattern($page, $schema); 138 139 $request = new \TestRequest(); 140 $response = $request->get(['id' => $page, 'do' => 'edit'], '/doku.php'); 141 $test_html = trim($response->queryHTML('.struct_entry_form')->html()); 142 143 $doc = new Document(); 144 $doc->loadHTML($test_html); 145 $this->assertEquals('schema2', $doc->find('legend')->text()); 146 $this->checkField($doc, 'schema2', 'afirst', ''); 147 $this->checkField($doc, 'schema2', 'asecond', ''); 148 $this->checkField($doc, 'schema2', 'athird', ''); 149 $this->checkField($doc, 'schema2', 'afourth', ''); 150 } 151 152 public function test_preview_page_invaliddata() 153 { 154 $page = 'test_preview_page_invaliddata'; 155 $assignment = Assignments::getInstance(); 156 $schema = 'schema2'; 157 $assignment->addPattern($page, $schema); 158 159 $request = new \TestRequest(); 160 $structData = [ 161 $schema => [ 162 'afirst' => 'foo', 163 'asecond' => 'bar, baz', 164 'athird' => 'foobar', 165 'afourth' => 'Eve' 166 ] 167 ]; 168 $request->setPost('struct_schema_data', $structData); 169 $response = $request->post(['id' => $page, 'do' => 'preview'], '/doku.php'); 170 $expected_errormsg = sprintf($this->getLang('validation_prefix') . $this->getLang('Validation Exception Decimal needed'), 'afourth'); 171 $actual_errormsg = $response->queryHTML('.error')->html(); 172 $test_html = trim($response->queryHTML('.struct_entry_form')->html()); 173 174 $this->assertEquals($expected_errormsg, $actual_errormsg, 'If there is invalid data, then there should be an error message.'); 175 176 $doc = new Document(); 177 $doc->loadHTML($test_html); 178 $this->assertEquals('schema2', $doc->find('legend')->text()); 179 $this->checkField($doc, 'schema2', 'afirst', 'foo'); 180 $this->checkField($doc, 'schema2', 'asecond', 'bar, baz'); 181 $this->checkField($doc, 'schema2', 'athird', 'foobar'); 182 $this->checkField($doc, 'schema2', 'afourth', 'Eve'); 183 } 184 185 public function test_preview_page_validdata() 186 { 187 $page = 'test_preview_page_validdata'; 188 $assignment = Assignments::getInstance(); 189 $schema = 'schema2'; 190 $assignment->addPattern($page, $schema); 191 192 $request = new \TestRequest(); 193 $structData = [ 194 $schema => [ 195 'afirst' => 'foo', 196 'asecond' => 'bar, baz', 197 'athird' => 'foobar', 198 'afourth' => '42' 199 ] 200 ]; 201 $request->setPost('struct_schema_data', $structData); 202 $response = $request->post(['id' => $page, 'do' => 'preview']); 203 $actual_errormsg = $response->queryHTML('.error')->get(0); 204 $this->assertNull($actual_errormsg, "If all data is valid, then there should be no error message."); 205 206 $test_html = trim($response->queryHTML('.struct_entry_form')->html()); 207 208 $doc = new Document(); 209 $doc->loadHTML($test_html); 210 $this->assertEquals('schema2', $doc->find('legend')->text()); 211 $this->checkField($doc, 'schema2', 'afirst', 'foo'); 212 $this->checkField($doc, 'schema2', 'asecond', 'bar, baz'); 213 $this->checkField($doc, 'schema2', 'athird', 'foobar'); 214 $this->checkField($doc, 'schema2', 'afourth', '42'); 215 } 216 217 public function test_fail_saving_empty_page() 218 { 219 $page = 'test_fail_saving_empty_page'; 220 $assignment = Assignments::getInstance(); 221 $schema = 'schema2'; 222 $assignment->addPattern($page, $schema); 223 224 $request = new \TestRequest(); 225 $structData = [ 226 $schema => [ 227 'afirst' => 'foo', 228 'asecond' => 'bar, baz', 229 'athird' => 'foobar', 230 'afourth' => '42' 231 ] 232 ]; 233 $request->setPost('struct_schema_data', $structData); 234 $request->setPost('summary', 'only struct data saved'); 235 $response = $request->post(['id' => $page, 'do' => 'save'], '/doku.php'); 236 $expected_errormsg = $this->getLang('emptypage'); 237 $actual_errormsg = $response->queryHTML('.error')->html(); 238 $pagelog = new \PageChangelog($page); 239 $revisions = $pagelog->getRevisions(-1, 200); 240 241 $this->assertCount(0, $revisions); 242 $this->assertEquals($expected_errormsg, $actual_errormsg, "An empty page should not be saved."); 243 } 244 245 public function test_fail_saveing_page_with_invaliddata() 246 { 247 $page = 'test_fail_saveing_page_with_invaliddata'; 248 $assignment = Assignments::getInstance(); 249 $schema = 'schema2'; 250 $assignment->addPattern($page, $schema); 251 252 $wikitext = 'teststring'; 253 $request = new \TestRequest(); 254 $structData = [ 255 $schema => [ 256 'afirst' => 'foo', 257 'asecond' => 'bar, baz', 258 'athird' => 'foobar', 259 'afourth' => 'Eve' 260 ] 261 ]; 262 $request->setPost('struct_schema_data', $structData); 263 $request->setPost('wikitext', $wikitext); 264 $request->setPost('summary', 'content and struct data saved'); 265 $response = $request->post(['id' => $page, 'do' => 'save'], '/doku.php'); 266 $actual_wikitext = trim($response->queryHTML('#wiki__text')->html()); 267 $expected_wikitext = $wikitext; 268 269 $actual_errormsg = $response->queryHTML('.error')->html(); 270 $expected_errormsg = sprintf($this->getLang('validation_prefix') . $this->getLang('Validation Exception Decimal needed'), 'afourth'); 271 272 $test_html = trim($response->queryHTML('.struct_entry_form')->html()); 273 274 $pagelog = new \PageChangelog($page); 275 $revisions = $pagelog->getRevisions(-1, 200); 276 277 // assert 278 $this->assertCount(0, $revisions); 279 $this->assertEquals($expected_errormsg, $actual_errormsg, 'If there is invalid data, then there should be an error message.'); 280 $this->assertEquals($expected_wikitext, $actual_wikitext); 281 282 $doc = new Document(); 283 $doc->loadHTML($test_html); 284 $this->assertEquals('schema2', $doc->find('legend')->text()); 285 $this->checkField($doc, 'schema2', 'afirst', 'foo'); 286 $this->checkField($doc, 'schema2', 'asecond', 'bar, baz'); 287 $this->checkField($doc, 'schema2', 'athird', 'foobar'); 288 $this->checkField($doc, 'schema2', 'afourth', 'Eve'); 289 290 // todo: assert that no struct data has been saved 291 } 292 293 public function test_save_page() 294 { 295 $page = 'test_save_page'; 296 $assignment = Assignments::getInstance(); 297 $schema = 'schema2'; 298 $assignment->addPattern($page, $schema); 299 300 $request = new \TestRequest(); 301 $structData = [ 302 $schema => [ 303 'afirst' => 'foo', 304 'asecond' => 'bar, baz', 305 'athird' => 'foobar', 306 'afourth' => '42' 307 ] 308 ]; 309 $request->setPost('struct_schema_data', $structData); 310 $request->setPost('wikitext', 'teststring'); 311 $request->setPost('summary', 'content and struct data saved'); 312 $request->post(array('id' => $page, 'do' => 'save'), '/doku.php'); 313 314 $pagelog = new \PageChangelog($page); 315 $revisions = $pagelog->getRevisions(-1, 200); 316 $revinfo = $pagelog->getRevisionInfo($revisions[0]); 317 $schemaData = meta\AccessTable::getPageAccess($schema, $page, $revisions[0]); 318 $actual_struct_data = $schemaData->getDataArray(); 319 $expected_struct_data = [ 320 'afirst' => 'foo', 321 'asecond' => ['bar', 'baz'], 322 'athird' => 'foobar', 323 'afourth' => 42 324 ]; 325 326 $this->assertCount(1, $revisions); 327 $this->assertEquals('content and struct data saved', $revinfo['sum']); 328 $this->assertEquals(DOKU_CHANGE_TYPE_CREATE, $revinfo['type']); 329 $this->assertEquals($expected_struct_data, $actual_struct_data); 330 // todo: assert that pagerevision and struct data have the same timestamp 331 } 332 333 /** 334 * @group slow 335 */ 336 public function test_save_page_without_new_text() 337 { 338 $page = 'test_save_page_without_new_text'; 339 $assignment = Assignments::getInstance(); 340 $schema = 'schema2'; 341 $assignment->addPattern($page, $schema); 342 $wikitext = 'teststring'; 343 344 // first save; 345 $request = new \TestRequest(); 346 $structData = [ 347 $schema => [ 348 'afirst' => 'foo', 349 'asecond' => 'bar, baz', 350 'athird' => 'foobar', 351 'afourth' => '42' 352 ] 353 ]; 354 $request->setPost('struct_schema_data', $structData); 355 $request->setPost('wikitext', $wikitext); 356 $request->setPost('summary', 'content and struct data saved'); 357 $request->post(['id' => $page, 'do' => 'save'], '/doku.php'); 358 359 $this->waitForTick(true); 360 361 // second save - only struct data 362 $request = new \TestRequest(); 363 $structData = [ 364 $schema => [ 365 'afirst' => 'foo2', 366 'asecond' => 'bar2, baz2', 367 'athird' => 'foobar2', 368 'afourth' => '43' 369 ] 370 ]; 371 $request->setPost('struct_schema_data', $structData); 372 $request->setPost('wikitext', $wikitext); 373 $request->setPost('summary', '2nd revision'); 374 $request->post(['id' => $page, 'do' => 'save'], '/doku.php'); 375 376 // assert 377 $pagelog = new \PageChangelog($page); 378 $revisions = $pagelog->getRevisions(-1, 200); 379 $revinfo = $pagelog->getRevisionInfo($revisions[0]); 380 $schemaData = meta\AccessTable::getPageAccess($schema, $page, $revisions[0]); 381 $actual_struct_data = $schemaData->getDataArray(); 382 $expected_struct_data = [ 383 'afirst' => 'foo2', 384 'asecond' => ['bar2', 'baz2'], 385 'athird' => 'foobar2', 386 'afourth' => 43 387 ]; 388 389 $this->assertCount(2, $revisions, 'there should be 2 (two) revisions'); 390 $this->assertEquals('2nd revision', $revinfo['sum']); 391 $this->assertEquals(DOKU_CHANGE_TYPE_EDIT, $revinfo['type']); 392 $this->assertEquals($expected_struct_data, $actual_struct_data); 393 // todo: assert that pagerevisions and struct entries have the same timestamps 394 } 395 396 /** 397 * @group slow 398 */ 399 public function test_delete_page() 400 { 401 $page = 'test_delete_page'; 402 $assignment = Assignments::getInstance(); 403 $schema = 'schema2'; 404 $assignment->addPattern($page, $schema); 405 $wikitext = 'teststring'; 406 407 // first save; 408 $request = new \TestRequest(); 409 $structData = [ 410 $schema => [ 411 'afirst' => 'foo', 412 'asecond' => 'bar, baz', 413 'athird' => 'foobar', 414 'afourth' => '42' 415 ] 416 ]; 417 $request->setPost('struct_schema_data', $structData); 418 $request->setPost('wikitext', $wikitext); 419 $request->setPost('summary', 'content and struct data saved'); 420 $request->post(['id' => $page, 'do' => 'save'], '/doku.php'); 421 422 $this->waitForTick(true); 423 424 // delete 425 $request = new \TestRequest(); 426 $structData = [ 427 $schema => [ 428 'afirst' => 'foo2', 429 'asecond' => 'bar2, baz2', 430 'athird' => 'foobar2', 431 'afourth' => '43' 432 ] 433 ]; 434 $request->setPost('struct_schema_data', $structData); 435 $request->setPost('wikitext', ''); 436 $request->setPost('summary', 'delete page'); 437 $request->post(['id' => $page, 'do' => 'save'], '/doku.php'); 438 439 // assert 440 $pagelog = new \PageChangelog($page); 441 $revisions = $pagelog->getRevisions(-1, 200); 442 $revinfo = $pagelog->getRevisionInfo($revisions[0]); 443 $schemaData = meta\AccessTable::getPageAccess($schema, $page, $revisions[0]); 444 $actual_struct_data = $schemaData->getDataArray(); 445 $expected_struct_data = [ 446 'afirst' => '', 447 'asecond' => [], 448 'athird' => '', 449 'afourth' => '' 450 ]; 451 452 $this->assertCount(2, $revisions, 'there should be 2 (two) revisions'); 453 $this->assertEquals('delete page', $revinfo['sum']); 454 $this->assertEquals(DOKU_CHANGE_TYPE_DELETE, $revinfo['type']); 455 $this->assertEquals($expected_struct_data, $actual_struct_data); 456 // todo: timestamps? 457 } 458 459 /** 460 * @group slow 461 */ 462 public function test_revert_page() 463 { 464 $page = 'test_revert_page'; 465 $assignment = Assignments::getInstance(); 466 $schema = 'schema2'; 467 $assignment->addPattern($page, $schema); 468 $wikitext = 'teststring'; 469 470 global $conf; 471 $conf['useacl'] = 1; 472 $conf['superuser'] = 'admin'; 473 $_SERVER['REMOTE_USER'] = 'admin'; //now it's testing as admin 474 global $default_server_vars; 475 $default_server_vars['REMOTE_USER'] = 'admin'; //Hack until Issue #1099 is fixed 476 global $USERINFO; 477 $USERINFO['name'] = 'admin'; 478 $USERINFO['mail'] = 'admin@example.com'; 479 $USERINFO['grps'] = ['admin', 'user']; 480 481 // first save; 482 $request = new \TestRequest(); 483 $structData = [ 484 $schema => [ 485 'afirst' => 'foo', 486 'asecond' => 'bar, baz', 487 'athird' => 'foobar', 488 'afourth' => '42' 489 ] 490 ]; 491 $request->setPost('struct_schema_data', $structData); 492 $request->setPost('wikitext', $wikitext); 493 $request->setPost('summary', 'content and struct data saved'); 494 $request->post(['id' => $page, 'do' => 'save', 'sectok' => getSecurityToken()], '/doku.php'); 495 496 $this->waitForTick(true); 497 498 // second save 499 $request = new \TestRequest(); 500 $structData = [ 501 $schema => [ 502 'afirst' => 'foo2', 503 'asecond' => 'bar2, baz2', 504 'athird' => 'foobar2', 505 'afourth' => '43' 506 ] 507 ]; 508 $request->setPost('struct_schema_data', $structData); 509 $request->setPost('wikitext', $wikitext . $wikitext); 510 $request->setPost('summary', 'delete page'); 511 $request->post(['id' => $page, 'do' => 'save', 'sectok' => getSecurityToken()], '/doku.php'); 512 513 $this->waitForTick(true); 514 515 // revert to first save 516 $actpagelog = new \PageChangelog($page); 517 $actrevisions = $actpagelog->getRevisions(0, 200); 518 519 $actrevinfo = $actpagelog->getRevisionInfo($actrevisions[0]); 520 $request = new \TestRequest(); 521 $request->setPost('summary', 'revert page'); 522 $request->post(['id' => $page, 'do' => 'revert', 'rev' => $actrevinfo['date'], 'sectok' => getSecurityToken()], '/doku.php'); 523 524 // assert 525 $pagelog = new \PageChangelog($page); 526 $revisions = $pagelog->getRevisions(-1, 200); 527 $revinfo = $pagelog->getRevisionInfo($revisions[0]); 528 $schemaData = meta\AccessTable::getPageAccess($schema, $page, $revisions[0]); 529 $actual_struct_data = $schemaData->getDataArray(); 530 $expected_struct_data = [ 531 'afirst' => 'foo', 532 'asecond' => ['bar', 'baz'], 533 'athird' => 'foobar', 534 'afourth' => '42' 535 ]; 536 537 $this->assertCount(3, $revisions, 'there should be 3 (three) revisions'); 538 $this->assertStringContainsString('restored', $revinfo['sum']); 539 $this->assertEquals(DOKU_CHANGE_TYPE_REVERT, $revinfo['type']); 540 $this->assertEquals($expected_struct_data, $actual_struct_data); 541 // todo: timestamps? 542 } 543 544} 545