3 namespace Tests\Entity;
5 use BookStack\Actions\ActivityType;
6 use BookStack\Entities\Models\Page;
7 use BookStack\Entities\Repos\PageRepo;
10 class PageRevisionTest extends TestCase
12 public function test_page_revision_views_viewable()
16 $pageRepo = app(PageRepo::class);
17 $page = Page::first();
18 $pageRepo->update($page, ['name' => 'updated page', 'html' => '<p>new content</p>', 'summary' => 'page revision testing']);
19 $pageRevision = $page->revisions->last();
21 $revisionView = $this->get($page->getUrl() . '/revisions/' . $pageRevision->id);
22 $revisionView->assertStatus(200);
23 $revisionView->assertSee('new content');
25 $revisionView = $this->get($page->getUrl() . '/revisions/' . $pageRevision->id . '/changes');
26 $revisionView->assertStatus(200);
27 $revisionView->assertSee('new content');
30 public function test_page_revision_preview_shows_content_of_revision()
34 $pageRepo = app(PageRepo::class);
35 $page = Page::first();
36 $pageRepo->update($page, ['name' => 'updated page', 'html' => '<p>new revision content</p>', 'summary' => 'page revision testing']);
37 $pageRevision = $page->revisions->last();
38 $pageRepo->update($page, ['name' => 'updated page', 'html' => '<p>Updated content</p>', 'summary' => 'page revision testing 2']);
40 $revisionView = $this->get($page->getUrl() . '/revisions/' . $pageRevision->id);
41 $revisionView->assertStatus(200);
42 $revisionView->assertSee('new revision content');
45 public function test_page_revision_restore_updates_content()
49 $pageRepo = app(PageRepo::class);
50 $page = Page::first();
51 $pageRepo->update($page, ['name' => 'updated page abc123', 'html' => '<p>new contente def456</p>', 'summary' => 'initial page revision testing']);
52 $pageRepo->update($page, ['name' => 'updated page again', 'html' => '<p>new content</p>', 'summary' => 'page revision testing']);
53 $page = Page::find($page->id);
55 $pageView = $this->get($page->getUrl());
56 $pageView->assertDontSee('abc123');
57 $pageView->assertDontSee('def456');
59 $revToRestore = $page->revisions()->where('name', 'like', '%abc123')->first();
60 $restoreReq = $this->put($page->getUrl() . '/revisions/' . $revToRestore->id . '/restore');
61 $page = Page::find($page->id);
63 $restoreReq->assertStatus(302);
64 $restoreReq->assertRedirect($page->getUrl());
66 $pageView = $this->get($page->getUrl());
67 $pageView->assertSee('abc123');
68 $pageView->assertSee('def456');
71 public function test_page_revision_restore_with_markdown_retains_markdown_content()
75 $pageRepo = app(PageRepo::class);
76 $page = Page::first();
77 $pageRepo->update($page, ['name' => 'updated page abc123', 'markdown' => '## New Content def456', 'summary' => 'initial page revision testing']);
78 $pageRepo->update($page, ['name' => 'updated page again', 'markdown' => '## New Content Updated', 'summary' => 'page revision testing']);
79 $page = Page::find($page->id);
81 $pageView = $this->get($page->getUrl());
82 $pageView->assertDontSee('abc123');
83 $pageView->assertDontSee('def456');
85 $revToRestore = $page->revisions()->where('name', 'like', '%abc123')->first();
86 $restoreReq = $this->put($page->getUrl() . '/revisions/' . $revToRestore->id . '/restore');
87 $page = Page::find($page->id);
89 $restoreReq->assertStatus(302);
90 $restoreReq->assertRedirect($page->getUrl());
92 $pageView = $this->get($page->getUrl());
93 $this->assertDatabaseHas('pages', [
95 'markdown' => '## New Content def456',
97 $pageView->assertSee('abc123');
98 $pageView->assertSee('def456');
101 public function test_page_revision_restore_sets_new_revision_with_summary()
105 $pageRepo = app(PageRepo::class);
106 $page = Page::first();
107 $pageRepo->update($page, ['name' => 'updated page abc123', 'html' => '<p>new contente def456</p>', 'summary' => 'My first update']);
108 $pageRepo->update($page, ['name' => 'updated page again', 'html' => '<p>new content</p>', 'summary' => '']);
111 $revToRestore = $page->revisions()->where('name', 'like', '%abc123')->first();
112 $this->put($page->getUrl() . '/revisions/' . $revToRestore->id . '/restore');
115 $this->assertDatabaseHas('page_revisions', [
116 'page_id' => $page->id,
117 'text' => 'new contente def456',
119 'summary' => "Restored from #{$revToRestore->id}; My first update",
122 $detail = "Revision #{$revToRestore->revision_number} (ID: {$revToRestore->id}) for page ID {$revToRestore->page_id}";
123 $this->assertActivityExists(ActivityType::REVISION_RESTORE, null, $detail);
126 public function test_page_revision_count_increments_on_update()
128 $page = Page::first();
129 $startCount = $page->revision_count;
130 $resp = $this->asEditor()->put($page->getUrl(), ['name' => 'Updated page', 'html' => 'new page html', 'summary' => 'Update a']);
131 $resp->assertStatus(302);
133 $this->assertTrue(Page::find($page->id)->revision_count === $startCount + 1);
136 public function test_revision_count_shown_in_page_meta()
138 $page = Page::first();
139 $this->asEditor()->put($page->getUrl(), ['name' => 'Updated page', 'html' => 'new page html', 'summary' => 'Update a']);
141 $page = Page::find($page->id);
142 $this->asEditor()->put($page->getUrl(), ['name' => 'Updated page', 'html' => 'new page html', 'summary' => 'Update a']);
144 $page = Page::find($page->id);
145 $pageView = $this->get($page->getUrl());
146 $pageView->assertSee('Revision #' . $page->revision_count);
149 public function test_revision_deletion()
151 /** @var Page $page */
152 $page = Page::query()->first();
153 $this->asEditor()->put($page->getUrl(), ['name' => 'Updated page', 'html' => 'new page html', 'summary' => 'Update a']);
156 $this->asEditor()->put($page->getUrl(), ['name' => 'Updated page', 'html' => 'new page html', 'summary' => 'Update a']);
159 $beforeRevisionCount = $page->revisions->count();
161 // Delete the first revision
162 $revision = $page->revisions->get(1);
163 $resp = $this->asEditor()->delete($revision->getUrl('/delete/'));
164 $resp->assertRedirect($page->getUrl('/revisions'));
167 $afterRevisionCount = $page->revisions->count();
169 $this->assertTrue($beforeRevisionCount === ($afterRevisionCount + 1));
171 $detail = "Revision #{$revision->revision_number} (ID: {$revision->id}) for page ID {$revision->page_id}";
172 $this->assertActivityExists(ActivityType::REVISION_DELETE, null, $detail);
174 // Try to delete the latest revision
175 $beforeRevisionCount = $page->revisions->count();
176 $resp = $this->asEditor()->delete($page->currentRevision->getUrl('/delete/'));
177 $resp->assertRedirect($page->getUrl('/revisions'));
180 $afterRevisionCount = $page->revisions->count();
181 $this->assertTrue($beforeRevisionCount === $afterRevisionCount);
184 public function test_revision_limit_enforced()
186 config()->set('app.revision_limit', 2);
187 $page = Page::first();
188 $this->asEditor()->put($page->getUrl(), ['name' => 'Updated page', 'html' => 'new page html', 'summary' => 'Update a']);
189 $page = Page::find($page->id);
190 $this->asEditor()->put($page->getUrl(), ['name' => 'Updated page', 'html' => 'new page html', 'summary' => 'Update a']);
191 for ($i = 0; $i < 10; $i++) {
192 $this->asEditor()->put($page->getUrl(), ['name' => 'Updated page', 'html' => 'new page html', 'summary' => 'Update a']);
195 $revisionCount = $page->revisions()->count();
196 $this->assertEquals(2, $revisionCount);
199 public function test_false_revision_limit_allows_many_revisions()
201 config()->set('app.revision_limit', false);
202 $page = Page::first();
203 $this->asEditor()->put($page->getUrl(), ['name' => 'Updated page', 'html' => 'new page html', 'summary' => 'Update a']);
204 $page = Page::find($page->id);
205 $this->asEditor()->put($page->getUrl(), ['name' => 'Updated page', 'html' => 'new page html', 'summary' => 'Update a']);
206 for ($i = 0; $i < 10; $i++) {
207 $this->asEditor()->put($page->getUrl(), ['name' => 'Updated page', 'html' => 'new page html', 'summary' => 'Update a']);
210 $revisionCount = $page->revisions()->count();
211 $this->assertEquals(12, $revisionCount);
214 public function test_revision_list_shows_editor_type()
216 /** @var Page $page */
217 $page = Page::first();
218 $this->asAdmin()->put($page->getUrl(), ['name' => 'Updated page', 'html' => 'new page html']);
220 $resp = $this->get($page->refresh()->getUrl('/revisions'));
221 $this->withHtml($resp)->assertElementContains('td', '(WYSIWYG)');
222 $this->withHtml($resp)->assertElementNotContains('td', '(Markdown)');
224 $this->asAdmin()->put($page->getUrl(), ['name' => 'Updated page', 'markdown' => '# Some markdown content']);
225 $resp = $this->get($page->refresh()->getUrl('/revisions'));
226 $this->withHtml($resp)->assertElementContains('td', '(Markdown)');