]> BookStack Code Mirror - bookstack/blob - tests/Api/RecycleBinApiTest.php
do some cleanup and add doc
[bookstack] / tests / Api / RecycleBinApiTest.php
1 <?php
2
3 namespace Tests\Api;
4
5 use BookStack\Entities\Models\Book;
6 use BookStack\Entities\Models\Deletion;
7 use BookStack\Entities\Models\Page;
8 use Illuminate\Support\Collection;
9 use Tests\TestCase;
10
11 class RecycleBinApiTest extends TestCase
12 {
13     use TestsApi;
14
15     protected string $baseEndpoint = '/api/recycle_bin';
16
17     protected array $endpointMap = [
18         ['get', '/api/recycle_bin'],
19         ['put', '/api/recycle_bin/1'],
20         ['delete', '/api/recycle_bin/1'],
21     ];
22
23     public function test_settings_manage_permission_needed_for_all_endpoints()
24     {
25         $editor = $this->getEditor();
26         $this->giveUserPermissions($editor, ['settings-manage']);
27         $this->actingAs($editor);
28
29         foreach ($this->endpointMap as [$method, $uri]) {
30             $resp = $this->json($method, $uri);
31             $resp->assertStatus(403);
32             $resp->assertJson($this->permissionErrorResponse());
33         }
34     }
35
36     public function test_restrictions_manage_all_permission_needed_for_all_endpoints()
37     {
38         $editor = $this->getEditor();
39         $this->giveUserPermissions($editor, ['restrictions-manage-all']);
40         $this->actingAs($editor);
41
42         foreach ($this->endpointMap as [$method, $uri]) {
43             $resp = $this->json($method, $uri);
44             $resp->assertStatus(403);
45             $resp->assertJson($this->permissionErrorResponse());
46         }
47     }
48
49     public function test_index_endpoint_returns_expected_page()
50     {
51         $this->actingAsAuthorizedUser();
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         $deletions = Deletion::query()->orderBy('id')->get();
60
61         $resp = $this->getJson($this->baseEndpoint);
62
63         $expectedData = $deletions
64             ->zip([$page, $book])
65             ->map(function (Collection $data) use ($editor) {
66                 return [
67                     'id'                => $data[0]->id,
68                     'deleted_by'        => $editor->getKey(),
69                     'created_at'        => $data[0]->created_at->toJson(),
70                     'updated_at'        => $data[0]->updated_at->toJson(),
71                     'deletable_type'    => $data[1]->getMorphClass(),
72                     'deletable_id'      => $data[1]->getKey(),
73                 ];
74             });
75
76         $resp->assertJson([
77             'data'  => $expectedData->values()->all(),
78             'total' => 2,
79         ]);
80     }
81
82     public function test_index_endpoint_returns_children()
83     {
84         $this->actingAsAuthorizedUser();
85
86         $book = Book::query()->whereHas('pages')->whereHas('chapters')->withCount(['pages', 'chapters'])->first();
87         $editor = $this->getEditor();
88         $this->actingAs($editor)->delete($book->getUrl());
89
90         $deletion = Deletion::query()->orderBy('id')->first();
91
92         $resp = $this->getJson($this->baseEndpoint);
93
94         $expectedData = [
95             [
96                 'id'                => $deletion->getKey(),
97                 'deleted_by'        => $editor->getKey(),
98                 'created_at'        => $deletion->created_at->toJson(),
99                 'updated_at'        => $deletion->updated_at->toJson(),
100                 'deletable_type'    => $book->getMorphClass(),
101                 'deletable_id'      => $book->getKey(),
102                 'children'          => [
103                     'BookStack\Page'    => $book->pages_count,
104                     'BookStack\Chapter' => $book->chapters_count,
105                 ],
106                 'parent' => null,
107             ],
108         ];
109
110         $resp->assertJson([
111             'data'  => $expectedData,
112             'total' => 1,
113         ]);
114     }
115
116     public function test_index_endpoint_returns_parent()
117     {
118         $this->actingAsAuthorizedUser();
119
120         $page = Page::query()->whereHas('chapter')->with('chapter')->first();
121
122         $editor = $this->getEditor();
123         $this->actingAs($editor)->delete($page->getUrl());
124
125         $deletion = Deletion::query()->orderBy('id')->first();
126
127         $resp = $this->getJson($this->baseEndpoint);
128
129         $expectedData = [
130             [
131                 'id'                => $deletion->getKey(),
132                 'deleted_by'        => $editor->getKey(),
133                 'created_at'        => $deletion->created_at->toJson(),
134                 'updated_at'        => $deletion->updated_at->toJson(),
135                 'deletable_type'    => $page->getMorphClass(),
136                 'deletable_id'      => $page->getKey(),
137                 'parent'            => [
138                     'type'  => 'BookStack\Chapter',
139                     'id'    => $page->chapter->getKey(),
140                 ],
141                 'children' => null,
142             ],
143         ];
144
145         $resp->assertJson([
146             'data'  => $expectedData,
147             'total' => 1,
148         ]);
149     }
150
151     public function test_restore_endpoint()
152     {
153         $this->actingAsAuthorizedUser();
154
155         $page = Page::query()->first();
156         $editor = $this->getEditor();
157         $this->actingAs($editor)->delete($page->getUrl());
158         $page->refresh();
159
160         $deletion = Deletion::query()->orderBy('id')->first();
161
162         $this->assertDatabaseHas('pages', [
163             'id'            => $page->getKey(),
164             'deleted_at'    => $page->deleted_at,
165         ]);
166
167         $this->putJson($this->baseEndpoint . '/' . $deletion->getKey());
168
169         $this->assertDatabaseHas('pages', [
170             'id'            => $page->getKey(),
171             'deleted_at'    => null,
172         ]);
173     }
174
175     public function test_destroy_endpoint()
176     {
177         $this->actingAsAuthorizedUser();
178
179         $page = Page::query()->first();
180         $editor = $this->getEditor();
181         $this->actingAs($editor)->delete($page->getUrl());
182         $page->refresh();
183
184         $deletion = Deletion::query()->orderBy('id')->first();
185
186         $this->assertDatabaseHas('pages', [
187             'id'            => $page->getKey(),
188             'deleted_at'    => $page->deleted_at,
189         ]);
190
191         $this->deleteJson($this->baseEndpoint . '/' . $deletion->getKey());
192         $this->assertDatabaseMissing('pages', ['id' => $page->getKey()]);
193     }
194
195     private function actingAsAuthorizedUser()
196     {
197         $editor = $this->getEditor();
198         $this->giveUserPermissions($editor, ['restrictions-manage-all']);
199         $this->giveUserPermissions($editor, ['settings-manage']);
200         $this->actingAs($editor);
201     }
202 }