1<?php 2 3namespace dokuwiki\test\Ui; 4 5use dokuwiki\Ui\PageDiff; 6 7/** 8 * Tests for the page diff view dokuwiki\Ui\PageDiff. 9 */ 10class PageDiffTest extends \DokuWikiTest 11{ 12 /** 13 * Determine which two revisions PageDiff would compare for a ?do=diff request 14 * that carries no rev or rev2 parameters. 15 * 16 * Clears any leftover request parameters, then runs PageDiff's internal request 17 * handler, which derives the default comparison pair from the changelog. Returns 18 * the timestamps it selected for the older and newer side of the diff. 19 * 20 * @param string $page page id to diff 21 * @return array the older (rev1) and newer (rev2) revision timestamps or false 22 */ 23 private function resolveDefaultDiff($page) 24 { 25 global $INPUT, $INFO; 26 // make sure no rev parameters leak in from a previous request 27 $INPUT->remove('rev'); 28 $INPUT->remove('rev2'); 29 $INFO['id'] = $page; 30 31 $diff = new PageDiff($page); 32 $this->callInaccessibleMethod($diff, 'handle', []); 33 return [ 34 $this->getInaccessibleProperty($diff, 'rev1'), 35 $this->getInaccessibleProperty($diff, 'rev2'), 36 ]; 37 } 38 39 /** 40 * Without rev parameters, the diff of an existing page compares the previous 41 * revision with the current one. 42 */ 43 public function testExistingPageComparesPreviousToCurrent() 44 { 45 $page = 'pagediff_existing'; 46 // the page file's mtime after each save is that revision's timestamp 47 saveWikiText($page, 'first content', 'create', false); 48 clearstatcache(); 49 $previous = filemtime(wikiFN($page)); 50 $this->waitForTick(true); 51 saveWikiText($page, 'second content', 'edit', false); 52 clearstatcache(); 53 $current = filemtime(wikiFN($page)); 54 55 [$rev1, $rev2] = $this->resolveDefaultDiff($page); 56 57 $this->assertEquals($previous, $rev1, 'older side should be the previous revision'); 58 $this->assertEquals($current, $rev2, 'newer side should be the current revision'); 59 } 60 61 /** 62 * Regression test for issue #4635: opening the default diff of a page deleted 63 * through DokuWiki compares the last edit with the deletion, instead of comparing 64 * the deletion entry with itself. 65 */ 66 public function testNormalDeletionComparesPreviousToDeletion() 67 { 68 $page = 'pagediff_deleted'; 69 saveWikiText($page, 'some content', 'create', false); 70 clearstatcache(); 71 $contentRev = filemtime(wikiFN($page)); // last revision that still had content 72 $this->waitForTick(true); 73 74 saveWikiText($page, '', 'delete', false); 75 clearstatcache(); 76 $this->assertFileDoesNotExist(wikiFN($page)); 77 78 [$rev1, $rev2] = $this->resolveDefaultDiff($page); 79 80 $this->assertEquals($contentRev, $rev1, 'older side should be the content revision before deletion'); 81 $this->assertGreaterThan( 82 $rev1, 83 $rev2, 84 'newer side must be the later deletion, not the same revision compared with itself' 85 ); 86 } 87 88 /** 89 * Regression test for issue #4635: opening the default diff of an externally 90 * deleted page compares the last edit with the persisted deletion, instead of 91 * comparing the deletion entry with itself. 92 */ 93 public function testExternalDeletionComparesPreviousToDeletion() 94 { 95 $page = 'pagediff_extdeleted'; 96 saveWikiText($page, 'some content', 'create', false); 97 clearstatcache(); 98 $contentRev = filemtime(wikiFN($page)); // last revision that still had content 99 100 // delete the page file externally, bypassing DokuWiki; resolving the diff is 101 // what triggers detection and persistence of the synthesized deletion entry, 102 // which is dated lastRev+1 at the earliest, so no tick is needed here 103 unlink(wikiFN($page)); 104 clearstatcache(); 105 106 [$rev1, $rev2] = $this->resolveDefaultDiff($page); 107 108 $this->assertEquals($contentRev, $rev1, 'older side should be the content revision before external deletion'); 109 $this->assertGreaterThan( 110 $rev1, 111 $rev2, 112 'newer side must be the later deletion, not the same revision compared with itself' 113 ); 114 } 115 116 /** 117 * Regression test for issue #4635: the rendered diff of a deleted page shows the 118 * removed content rather than an empty diff. 119 */ 120 public function testDeletionDiffRendersRemovedContent() 121 { 122 global $INPUT, $INFO; 123 124 $page = 'pagediff_removedcontent'; 125 saveWikiText($page, 'zqxdistinctivebody', 'create', false); 126 $this->waitForTick(true); 127 saveWikiText($page, '', 'delete', false); 128 clearstatcache(); 129 130 $INPUT->remove('rev'); 131 $INPUT->remove('rev2'); 132 $INFO['id'] = $page; 133 134 $diff = new PageDiff($page); 135 ob_start(); 136 $diff->show(); 137 $html = ob_get_clean(); 138 139 $this->assertStringContainsString( 140 'zqxdistinctivebody', 141 $html, 142 'the diff should display the removed content, not an empty diff' 143 ); 144 } 145} 146