5 use BookStack\Entities\Models\Book;
7 use Illuminate\Support\Facades\DB;
10 class BooksApiTest extends TestCase
14 protected string $baseEndpoint = '/api/books';
16 public function test_index_endpoint_returns_expected_book()
18 $this->actingAsApiEditor();
19 $firstBook = Book::query()->orderBy('id', 'asc')->first();
21 $resp = $this->getJson($this->baseEndpoint . '?count=1&sort=+id');
22 $resp->assertJson(['data' => [
24 'id' => $firstBook->id,
25 'name' => $firstBook->name,
26 'slug' => $firstBook->slug,
31 public function test_create_endpoint()
33 $this->actingAsApiEditor();
35 'name' => 'My API book',
36 'description' => 'A book created via the API',
39 $resp = $this->postJson($this->baseEndpoint, $details);
40 $resp->assertStatus(200);
41 $newItem = Book::query()->orderByDesc('id')->where('name', '=', $details['name'])->first();
42 $resp->assertJson(array_merge($details, ['id' => $newItem->id, 'slug' => $newItem->slug]));
43 $this->assertActivityExists('book_create', $newItem);
46 public function test_book_name_needed_to_create()
48 $this->actingAsApiEditor();
50 'description' => 'A book created via the API',
53 $resp = $this->postJson($this->baseEndpoint, $details);
54 $resp->assertStatus(422);
57 'message' => 'The given data was invalid.',
59 'name' => ['The name field is required.'],
66 public function test_read_endpoint()
68 $this->actingAsApiEditor();
69 $book = Book::visible()->first();
71 $resp = $this->getJson($this->baseEndpoint . "/{$book->id}");
73 $resp->assertStatus(200);
76 'slug' => $book->slug,
78 'name' => $book->createdBy->name,
81 'name' => $book->createdBy->name,
84 'name' => $book->ownedBy->name,
89 public function test_update_endpoint()
91 $this->actingAsApiEditor();
92 $book = Book::visible()->first();
94 'name' => 'My updated API book',
95 'description' => 'A book created via the API',
98 $resp = $this->putJson($this->baseEndpoint . "/{$book->id}", $details);
101 $resp->assertStatus(200);
102 $resp->assertJson(array_merge($details, ['id' => $book->id, 'slug' => $book->slug]));
103 $this->assertActivityExists('book_update', $book);
106 public function test_update_increments_updated_date_if_only_tags_are_sent()
108 $this->actingAsApiEditor();
109 $book = Book::visible()->first();
110 DB::table('books')->where('id', '=', $book->id)->update(['updated_at' => Carbon::now()->subWeek()]);
113 'tags' => [['name' => 'Category', 'value' => 'Testing']],
116 $this->putJson($this->baseEndpoint . "/{$book->id}", $details);
118 $this->assertGreaterThan(Carbon::now()->subDay()->unix(), $book->updated_at->unix());
121 public function test_delete_endpoint()
123 $this->actingAsApiEditor();
124 $book = Book::visible()->first();
125 $resp = $this->deleteJson($this->baseEndpoint . "/{$book->id}");
127 $resp->assertStatus(204);
128 $this->assertActivityExists('book_delete');
131 public function test_export_html_endpoint()
133 $this->actingAsApiEditor();
134 $book = Book::visible()->first();
136 $resp = $this->get($this->baseEndpoint . "/{$book->id}/export/html");
137 $resp->assertStatus(200);
138 $resp->assertSee($book->name);
139 $resp->assertHeader('Content-Disposition', 'attachment; filename="' . $book->slug . '.html"');
142 public function test_export_plain_text_endpoint()
144 $this->actingAsApiEditor();
145 $book = Book::visible()->first();
147 $resp = $this->get($this->baseEndpoint . "/{$book->id}/export/plaintext");
148 $resp->assertStatus(200);
149 $resp->assertSee($book->name);
150 $resp->assertHeader('Content-Disposition', 'attachment; filename="' . $book->slug . '.txt"');
153 public function test_export_pdf_endpoint()
155 $this->actingAsApiEditor();
156 $book = Book::visible()->first();
158 $resp = $this->get($this->baseEndpoint . "/{$book->id}/export/pdf");
159 $resp->assertStatus(200);
160 $resp->assertHeader('Content-Disposition', 'attachment; filename="' . $book->slug . '.pdf"');
163 public function test_export_markdown_endpoint()
165 $this->actingAsApiEditor();
166 $book = Book::visible()->has('pages')->has('chapters')->first();
168 $resp = $this->get($this->baseEndpoint . "/{$book->id}/export/markdown");
169 $resp->assertStatus(200);
170 $resp->assertHeader('Content-Disposition', 'attachment; filename="' . $book->slug . '.md"');
171 $resp->assertSee('# ' . $book->name);
172 $resp->assertSee('# ' . $book->pages()->first()->name);
173 $resp->assertSee('# ' . $book->chapters()->first()->name);
176 public function test_cant_export_when_not_have_permission()
178 $types = ['html', 'plaintext', 'pdf', 'markdown'];
179 $this->actingAsApiEditor();
180 $this->removePermissionFromUser($this->getEditor(), 'content-export');
182 $book = Book::visible()->first();
183 foreach ($types as $type) {
184 $resp = $this->get($this->baseEndpoint . "/{$book->id}/export/{$type}");
185 $this->assertPermissionError($resp);