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