]> BookStack Code Mirror - bookstack/blob - tests/RecycleBinTest.php
Added test coverage of recycle bin actions
[bookstack] / tests / RecycleBinTest.php
1 <?php namespace Tests;
2
3 use BookStack\Entities\Book;
4 use BookStack\Entities\Deletion;
5 use BookStack\Entities\Page;
6
7 class RecycleBinTest extends TestCase
8 {
9     public function test_recycle_bin_routes_permissions()
10     {
11         $page = Page::query()->first();
12         $editor = $this->getEditor();
13         $this->actingAs($editor)->delete($page->getUrl());
14         $deletion = Deletion::query()->firstOrFail();
15
16         $routes = [
17             'GET:/settings/recycle-bin',
18             'POST:/settings/recycle-bin/empty',
19             "GET:/settings/recycle-bin/{$deletion->id}/destroy",
20             "GET:/settings/recycle-bin/{$deletion->id}/restore",
21             "POST:/settings/recycle-bin/{$deletion->id}/restore",
22             "DELETE:/settings/recycle-bin/{$deletion->id}",
23         ];
24
25         foreach($routes as $route) {
26             [$method, $url] = explode(':', $route);
27             $resp = $this->call($method, $url);
28             $this->assertPermissionError($resp);
29         }
30
31         $this->giveUserPermissions($editor, ['restrictions-manage-all']);
32
33         foreach($routes as $route) {
34             [$method, $url] = explode(':', $route);
35             $resp = $this->call($method, $url);
36             $this->assertPermissionError($resp);
37         }
38
39         $this->giveUserPermissions($editor, ['settings-manage']);
40
41         foreach($routes as $route) {
42             \DB::beginTransaction();
43             [$method, $url] = explode(':', $route);
44             $resp = $this->call($method, $url);
45             $this->assertNotPermissionError($resp);
46             \DB::rollBack();
47         }
48
49     }
50
51     public function test_recycle_bin_view()
52     {
53         $page = Page::query()->first();
54         $book = Book::query()->whereHas('pages')->whereHas('chapters')->withCount(['pages', 'chapters'])->first();
55         $editor = $this->getEditor();
56         $this->actingAs($editor)->delete($page->getUrl());
57         $this->actingAs($editor)->delete($book->getUrl());
58
59         $viewReq = $this->asAdmin()->get('/settings/recycle-bin');
60         $viewReq->assertElementContains('table.table', $page->name);
61         $viewReq->assertElementContains('table.table', $editor->name);
62         $viewReq->assertElementContains('table.table', $book->name);
63         $viewReq->assertElementContains('table.table', $book->pages_count . ' Pages');
64         $viewReq->assertElementContains('table.table', $book->chapters_count . ' Chapters');
65     }
66
67     public function test_recycle_bin_empty()
68     {
69         $page = Page::query()->first();
70         $book = Book::query()->where('id' , '!=', $page->book_id)->whereHas('pages')->whereHas('chapters')->with(['pages', 'chapters'])->firstOrFail();
71         $editor = $this->getEditor();
72         $this->actingAs($editor)->delete($page->getUrl());
73         $this->actingAs($editor)->delete($book->getUrl());
74
75         $this->assertTrue(Deletion::query()->count() === 2);
76         $emptyReq = $this->asAdmin()->post('/settings/recycle-bin/empty');
77         $emptyReq->assertRedirect('/settings/recycle-bin');
78
79         $this->assertTrue(Deletion::query()->count() === 0);
80         $this->assertDatabaseMissing('books', ['id' => $book->id]);
81         $this->assertDatabaseMissing('pages', ['id' => $page->id]);
82         $this->assertDatabaseMissing('pages', ['id' => $book->pages->first()->id]);
83         $this->assertDatabaseMissing('chapters', ['id' => $book->chapters->first()->id]);
84
85         $itemCount = 2 + $book->pages->count() + $book->chapters->count();
86         $redirectReq = $this->get('/settings/recycle-bin');
87         $redirectReq->assertNotificationContains('Deleted '.$itemCount.' total items from the recycle bin');
88     }
89
90     public function test_entity_restore()
91     {
92         $book = Book::query()->whereHas('pages')->whereHas('chapters')->with(['pages', 'chapters'])->firstOrFail();
93         $this->asEditor()->delete($book->getUrl());
94         $deletion = Deletion::query()->firstOrFail();
95
96         $this->assertEquals($book->pages->count(), \DB::table('pages')->where('book_id', '=', $book->id)->whereNotNull('deleted_at')->count());
97         $this->assertEquals($book->chapters->count(), \DB::table('chapters')->where('book_id', '=', $book->id)->whereNotNull('deleted_at')->count());
98
99         $restoreReq = $this->asAdmin()->post("/settings/recycle-bin/{$deletion->id}/restore");
100         $restoreReq->assertRedirect('/settings/recycle-bin');
101         $this->assertTrue(Deletion::query()->count() === 0);
102
103         $this->assertEquals($book->pages->count(), \DB::table('pages')->where('book_id', '=', $book->id)->whereNull('deleted_at')->count());
104         $this->assertEquals($book->chapters->count(), \DB::table('chapters')->where('book_id', '=', $book->id)->whereNull('deleted_at')->count());
105
106         $itemCount = 1 + $book->pages->count() + $book->chapters->count();
107         $redirectReq = $this->get('/settings/recycle-bin');
108         $redirectReq->assertNotificationContains('Restored '.$itemCount.' total items from the recycle bin');
109     }
110
111     public function test_permanent_delete()
112     {
113         $book = Book::query()->whereHas('pages')->whereHas('chapters')->with(['pages', 'chapters'])->firstOrFail();
114         $this->asEditor()->delete($book->getUrl());
115         $deletion = Deletion::query()->firstOrFail();
116
117         $deleteReq = $this->asAdmin()->delete("/settings/recycle-bin/{$deletion->id}");
118         $deleteReq->assertRedirect('/settings/recycle-bin');
119         $this->assertTrue(Deletion::query()->count() === 0);
120
121         $this->assertDatabaseMissing('books', ['id' => $book->id]);
122         $this->assertDatabaseMissing('pages', ['id' => $book->pages->first()->id]);
123         $this->assertDatabaseMissing('chapters', ['id' => $book->chapters->first()->id]);
124
125         $itemCount = 1 + $book->pages->count() + $book->chapters->count();
126         $redirectReq = $this->get('/settings/recycle-bin');
127         $redirectReq->assertNotificationContains('Deleted '.$itemCount.' total items from the recycle bin');
128     }
129
130     public function test_permanent_entity_delete_updates_existing_activity_with_entity_name()
131     {
132         $page = Page::query()->firstOrFail();
133         $this->asEditor()->delete($page->getUrl());
134         $deletion = $page->deletions()->firstOrFail();
135
136         $this->assertDatabaseHas('activities', [
137             'key' => 'page_delete',
138             'entity_id' => $page->id,
139             'entity_type' => $page->getMorphClass(),
140         ]);
141
142         $this->asAdmin()->delete("/settings/recycle-bin/{$deletion->id}");
143
144         $this->assertDatabaseMissing('activities', [
145             'key' => 'page_delete',
146             'entity_id' => $page->id,
147             'entity_type' => $page->getMorphClass(),
148         ]);
149
150         $this->assertDatabaseHas('activities', [
151             'key' => 'page_delete',
152             'entity_id' => 0,
153             'entity_type' => '',
154             'extra' => $page->name,
155         ]);
156     }
157 }