5 use BookStack\Entities\Models\Book;
6 use BookStack\Entities\Models\Bookshelf;
8 use Illuminate\Support\Facades\DB;
10 use Tests\Uploads\UsesImages;
12 class ShelvesApiTest extends TestCase
17 protected string $baseEndpoint = '/api/shelves';
19 public function test_index_endpoint_returns_expected_shelf()
21 $this->actingAsApiEditor();
22 $firstBookshelf = Bookshelf::query()->orderBy('id', 'asc')->first();
24 $resp = $this->getJson($this->baseEndpoint . '?count=1&sort=+id');
25 $resp->assertJson(['data' => [
27 'id' => $firstBookshelf->id,
28 'name' => $firstBookshelf->name,
29 'slug' => $firstBookshelf->slug,
34 public function test_create_endpoint()
36 $this->actingAsApiEditor();
37 $books = Book::query()->take(2)->get();
40 'name' => 'My API shelf',
41 'description' => 'A shelf created via the API',
44 $resp = $this->postJson($this->baseEndpoint, array_merge($details, ['books' => [$books[0]->id, $books[1]->id]]));
45 $resp->assertStatus(200);
46 $newItem = Bookshelf::query()->orderByDesc('id')->where('name', '=', $details['name'])->first();
47 $resp->assertJson(array_merge($details, ['id' => $newItem->id, 'slug' => $newItem->slug]));
48 $this->assertActivityExists('bookshelf_create', $newItem);
49 foreach ($books as $index => $book) {
50 $this->assertDatabaseHas('bookshelves_books', [
51 'bookshelf_id' => $newItem->id,
52 'book_id' => $book->id,
58 public function test_shelf_name_needed_to_create()
60 $this->actingAsApiEditor();
62 'description' => 'A shelf created via the API',
65 $resp = $this->postJson($this->baseEndpoint, $details);
66 $resp->assertStatus(422);
69 'message' => 'The given data was invalid.',
71 'name' => ['The name field is required.'],
78 public function test_read_endpoint()
80 $this->actingAsApiEditor();
81 $shelf = Bookshelf::visible()->first();
83 $resp = $this->getJson($this->baseEndpoint . "/{$shelf->id}");
85 $resp->assertStatus(200);
88 'slug' => $shelf->slug,
90 'name' => $shelf->createdBy->name,
93 'name' => $shelf->createdBy->name,
96 'name' => $shelf->ownedBy->name,
101 public function test_update_endpoint()
103 $this->actingAsApiEditor();
104 $shelf = Bookshelf::visible()->first();
106 'name' => 'My updated API shelf',
107 'description' => 'A shelf created via the API',
110 $resp = $this->putJson($this->baseEndpoint . "/{$shelf->id}", $details);
113 $resp->assertStatus(200);
114 $resp->assertJson(array_merge($details, ['id' => $shelf->id, 'slug' => $shelf->slug]));
115 $this->assertActivityExists('bookshelf_update', $shelf);
118 public function test_update_increments_updated_date_if_only_tags_are_sent()
120 $this->actingAsApiEditor();
121 $shelf = Bookshelf::visible()->first();
122 DB::table('bookshelves')->where('id', '=', $shelf->id)->update(['updated_at' => Carbon::now()->subWeek()]);
125 'tags' => [['name' => 'Category', 'value' => 'Testing']],
128 $this->putJson($this->baseEndpoint . "/{$shelf->id}", $details);
130 $this->assertGreaterThan(Carbon::now()->subDay()->unix(), $shelf->updated_at->unix());
133 public function test_update_only_assigns_books_if_param_provided()
135 $this->actingAsApiEditor();
136 $shelf = Bookshelf::visible()->first();
137 $this->assertTrue($shelf->books()->count() > 0);
139 'name' => 'My updated API shelf',
142 $resp = $this->putJson($this->baseEndpoint . "/{$shelf->id}", $details);
143 $resp->assertStatus(200);
144 $this->assertTrue($shelf->books()->count() > 0);
146 $resp = $this->putJson($this->baseEndpoint . "/{$shelf->id}", ['books' => []]);
147 $resp->assertStatus(200);
148 $this->assertTrue($shelf->books()->count() === 0);
151 public function test_update_cover_image_control()
153 $this->actingAsApiEditor();
154 /** @var Book $shelf */
155 $shelf = Bookshelf::visible()->first();
156 $this->assertNull($shelf->cover);
157 $file = $this->getTestImage('image.png');
159 // Ensure cover image can be set via API
160 $resp = $this->call('PUT', $this->baseEndpoint . "/{$shelf->id}", [
161 'name' => 'My updated API shelf with image',
162 ], [], ['image' => $file]);
165 $resp->assertStatus(200);
166 $this->assertNotNull($shelf->cover);
168 // Ensure further updates without image do not clear cover image
169 $resp = $this->put($this->baseEndpoint . "/{$shelf->id}", [
170 'name' => 'My updated shelf again',
174 $resp->assertStatus(200);
175 $this->assertNotNull($shelf->cover);
177 // Ensure update with null image property clears image
178 $resp = $this->put($this->baseEndpoint . "/{$shelf->id}", [
183 $resp->assertStatus(200);
184 $this->assertNull($shelf->cover);
187 public function test_delete_endpoint()
189 $this->actingAsApiEditor();
190 $shelf = Bookshelf::visible()->first();
191 $resp = $this->deleteJson($this->baseEndpoint . "/{$shelf->id}");
193 $resp->assertStatus(204);
194 $this->assertActivityExists('bookshelf_delete');