]> BookStack Code Mirror - bookstack/blob - tests/Api/ImportsApiTest.php
ZIP Imports: Added API test cases
[bookstack] / tests / Api / ImportsApiTest.php
1 <?php
2
3 namespace Api;
4
5 use BookStack\Entities\Models\Page;
6 use BookStack\Exports\Import;
7 use Tests\Api\TestsApi;
8 use Tests\Exports\ZipTestHelper;
9 use Tests\TestCase;
10
11 class ImportsApiTest extends TestCase
12 {
13     use TestsApi;
14
15     protected string $baseEndpoint = '/api/imports';
16
17     public function test_upload_and_run(): void
18     {
19         $book = $this->entities->book();
20         $zip = ZipTestHelper::zipUploadFromData([
21             'page' => [
22                 'name' => 'My API import page',
23                 'tags' => [
24                     [
25                         'name' => 'My api tag',
26                         'value' => 'api test value'
27                     ]
28                 ],
29             ],
30         ]);
31
32         $resp = $this->actingAsApiAdmin()->call('POST', $this->baseEndpoint, [], [], ['file' => $zip]);
33         $resp->assertStatus(200);
34
35         $importId = $resp->json('id');
36         $import = Import::query()->findOrFail($importId);
37         $this->assertEquals('page', $import->type);
38
39         $resp = $this->post($this->baseEndpoint . "/{$import->id}", [
40             'parent_type' => 'book',
41             'parent_id' => $book->id,
42         ]);
43         $resp->assertJson([
44             'name' => 'My API import page',
45             'book_id' => $book->id,
46         ]);
47
48         $page = Page::query()->where('name', '=', 'My API import page')->first();
49         $this->assertEquals('My api tag', $page->tags()->first()->name);
50     }
51
52     public function test_upload_validation_error(): void
53     {
54         $zip = ZipTestHelper::zipUploadFromData([
55             'page' => [
56                 'tags' => [
57                     [
58                         'name' => 'My api tag',
59                         'value' => 'api test value'
60                     ]
61                 ],
62             ],
63         ]);
64
65         $resp = $this->actingAsApiAdmin()->call('POST', $this->baseEndpoint, [], [], ['file' => $zip]);
66         $resp->assertStatus(422);
67         $message = $resp->json('message');
68
69         $this->assertStringContainsString('ZIP upload failed with the following validation errors:', $message);
70         $this->assertStringContainsString('[page.name] The name field is required.', $message);
71     }
72
73     public function test_list(): void
74     {
75         $imports = Import::factory()->count(10)->create();
76
77         $resp = $this->actingAsApiAdmin()->get($this->baseEndpoint);
78         $resp->assertJsonCount(10, 'data');
79         $resp->assertJsonPath('total', 10);
80
81         $firstImport = $imports->first();
82         $resp = $this->actingAsApiAdmin()->get($this->baseEndpoint . '?filter[id]=' . $firstImport->id);
83         $resp->assertJsonCount(1, 'data');
84         $resp->assertJsonPath('data.0.id', $firstImport->id);
85         $resp->assertJsonPath('data.0.name', $firstImport->name);
86         $resp->assertJsonPath('data.0.size', $firstImport->size);
87         $resp->assertJsonPath('data.0.type', $firstImport->type);
88     }
89
90     public function test_list_visibility_limited(): void
91     {
92         $user = $this->users->editor();
93         $admin = $this->users->admin();
94         $userImport = Import::factory()->create(['name' => 'MySuperUserImport', 'created_by' => $user->id]);
95         $adminImport = Import::factory()->create(['name' => 'MySuperAdminImport', 'created_by' => $admin->id]);
96         $this->permissions->grantUserRolePermissions($user, ['content-import']);
97
98         $resp = $this->actingAsForApi($user)->get($this->baseEndpoint);
99         $resp->assertJsonCount(1, 'data');
100         $resp->assertJsonPath('data.0.name', 'MySuperUserImport');
101
102         $this->permissions->grantUserRolePermissions($user, ['settings-manage']);
103
104         $resp = $this->actingAsForApi($user)->get($this->baseEndpoint);
105         $resp->assertJsonCount(2, 'data');
106         $resp->assertJsonPath('data.1.name', 'MySuperAdminImport');
107     }
108
109     public function test_read(): void
110     {
111         $zip = ZipTestHelper::zipUploadFromData([
112             'book' => [
113                 'name' => 'My API import book',
114                 'pages' => [
115                     [
116                         'name' => 'My import page',
117                         'tags' => [
118                             [
119                                 'name' => 'My api tag',
120                                 'value' => 'api test value'
121                             ]
122                         ]
123                     ]
124                 ],
125             ],
126         ]);
127
128         $resp = $this->actingAsApiAdmin()->call('POST', $this->baseEndpoint, [], [], ['file' => $zip]);
129         $resp->assertStatus(200);
130
131         $resp = $this->get($this->baseEndpoint . "/{$resp->json('id')}");
132         $resp->assertStatus(200);
133
134         $resp->assertJsonPath('details.name', 'My API import book');
135         $resp->assertJsonPath('details.pages.0.name', 'My import page');
136         $resp->assertJsonPath('details.pages.0.tags.0.name', 'My api tag');
137         $resp->assertJsonMissingPath('metadata');
138     }
139
140     public function test_delete(): void
141     {
142         $import = Import::factory()->create();
143
144         $resp = $this->actingAsApiAdmin()->delete($this->baseEndpoint . "/{$import->id}");
145         $resp->assertStatus(204);
146     }
147
148     public function test_content_import_permissions_needed(): void
149     {
150         $user = $this->users->viewer();
151         $this->permissions->grantUserRolePermissions($user, ['access-api']);
152         $this->actingAsForApi($user);
153         $requests = [
154              ['GET', $this->baseEndpoint],
155              ['POST', $this->baseEndpoint],
156              ['GET', $this->baseEndpoint . "/1"],
157              ['POST', $this->baseEndpoint . "/1"],
158              ['DELETE', $this->baseEndpoint . "/1"],
159         ];
160
161         foreach ($requests as $request) {
162             [$method, $endpoint] = $request;
163             $resp = $this->json($method, $endpoint);
164             $resp->assertStatus(403);
165         }
166
167         $this->permissions->grantUserRolePermissions($user, ['content-import']);
168
169         foreach ($requests as $request) {
170             [$method, $endpoint] = $request;
171             $resp = $this->call($method, $endpoint);
172             $this->assertNotEquals(403, $resp->status(), "A {$method} request to {$endpoint} returned 403");
173         }
174     }
175 }