Filled out base Book API endpoints, added example responses
This commit is contained in:
		
							parent
							
								
									a8595d8aaf
								
							
						
					
					
						commit
						04a8614136
					
				| 
						 | 
					@ -47,7 +47,7 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
 | 
				
			||||||
     * The attributes excluded from the model's JSON form.
 | 
					     * The attributes excluded from the model's JSON form.
 | 
				
			||||||
     * @var array
 | 
					     * @var array
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected $hidden = ['password', 'remember_token'];
 | 
					    protected $hidden = ['password', 'remember_token', 'system_name', 'email_confirmed', 'external_auth_id', 'email'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * This holds the user's permissions when loaded.
 | 
					     * This holds the user's permissions when loaded.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,7 +18,8 @@ class Book extends Entity implements HasCoverImage
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    public $searchFactor = 2;
 | 
					    public $searchFactor = 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected $fillable = ['name', 'description', 'image_id'];
 | 
					    protected $fillable = ['name', 'description'];
 | 
				
			||||||
 | 
					    protected $hidden = ['restricted'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Get the url for this book.
 | 
					     * Get the url for this book.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,6 +8,8 @@ use Illuminate\Http\JsonResponse;
 | 
				
			||||||
class ApiController extends Controller
 | 
					class ApiController extends Controller
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected $rules = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Provide a paginated listing JSON response in a standard format
 | 
					     * Provide a paginated listing JSON response in a standard format
 | 
				
			||||||
     * taking into account any pagination parameters passed by the user.
 | 
					     * taking into account any pagination parameters passed by the user.
 | 
				
			||||||
| 
						 | 
					@ -17,4 +19,12 @@ class ApiController extends Controller
 | 
				
			||||||
        $listing = new ListingResponseBuilder($query, request(), $fields);
 | 
					        $listing = new ListingResponseBuilder($query, request(), $fields);
 | 
				
			||||||
        return $listing->toResponse();
 | 
					        return $listing->toResponse();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get the validation rules for this controller.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function getValdationRules(): array
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->rules;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,47 +1,99 @@
 | 
				
			||||||
<?php namespace BookStack\Http\Controllers\Api;
 | 
					<?php namespace BookStack\Http\Controllers\Api;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use BookStack\Entities\Book;
 | 
					use BookStack\Entities\Book;
 | 
				
			||||||
 | 
					use BookStack\Entities\Repos\BookRepo;
 | 
				
			||||||
 | 
					use BookStack\Facades\Activity;
 | 
				
			||||||
 | 
					use Illuminate\Http\Request;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class BooksApiController extends ApiController
 | 
					class BooksApiController extends ApiController
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    public $validation = [
 | 
					
 | 
				
			||||||
 | 
					    protected $bookRepo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected $rules = [
 | 
				
			||||||
        'create' => [
 | 
					        'create' => [
 | 
				
			||||||
            // TODO
 | 
					            'name' => 'required|string|max:255',
 | 
				
			||||||
 | 
					            'description' => 'string|max:1000',
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
        'update' => [
 | 
					        'update' => [
 | 
				
			||||||
            // TODO
 | 
					            'name' => 'string|min:1|max:255',
 | 
				
			||||||
 | 
					            'description' => 'string|max:1000',
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
    ];
 | 
					    ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * BooksApiController constructor.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function __construct(BookRepo $bookRepo)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->bookRepo = $bookRepo;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Get a listing of books visible to the user.
 | 
					     * Get a listing of books visible to the user.
 | 
				
			||||||
 | 
					     * @api listing
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function index()
 | 
					    public function index()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $books = Book::visible();
 | 
					        $books = Book::visible();
 | 
				
			||||||
        return $this->apiListingResponse($books, [
 | 
					        return $this->apiListingResponse($books, [
 | 
				
			||||||
            'id', 'name', 'slug', 'description', 'created_at', 'updated_at', 'created_by', 'updated_by',
 | 
					            'id', 'name', 'slug', 'description', 'created_at', 'updated_at', 'created_by', 'updated_by', 'image_id',
 | 
				
			||||||
            'restricted', 'image_id',
 | 
					 | 
				
			||||||
        ]);
 | 
					        ]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function create()
 | 
					    /**
 | 
				
			||||||
 | 
					     * Create a new book.
 | 
				
			||||||
 | 
					     * @throws \Illuminate\Validation\ValidationException
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function create(Request $request)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        // TODO -
 | 
					        $this->checkPermission('book-create-all');
 | 
				
			||||||
 | 
					        $requestData = $this->validate($request, $this->rules['create']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $book = $this->bookRepo->create($requestData);
 | 
				
			||||||
 | 
					        Activity::add($book, 'book_create', $book->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return response()->json($book);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function read()
 | 
					    /**
 | 
				
			||||||
 | 
					     * View the details of a single book.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function read(string $id)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        // TODO -
 | 
					        $book = Book::visible()->with(['tags', 'cover', 'createdBy', 'updatedBy'])->findOrFail($id);
 | 
				
			||||||
 | 
					        return response()->json($book);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function update()
 | 
					    /**
 | 
				
			||||||
 | 
					     * Update the details of a single book.
 | 
				
			||||||
 | 
					     * @throws \Illuminate\Validation\ValidationException
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function update(Request $request, string $id)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        // TODO -
 | 
					        $book = Book::visible()->findOrFail($id);
 | 
				
			||||||
 | 
					        $this->checkOwnablePermission('book-update', $book);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $requestData = $this->validate($request, $this->rules['update']);
 | 
				
			||||||
 | 
					        $book = $this->bookRepo->update($book, $requestData);
 | 
				
			||||||
 | 
					        Activity::add($book, 'book_update', $book->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return response()->json($book);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function delete()
 | 
					    /**
 | 
				
			||||||
 | 
					     * Delete a book from the system.
 | 
				
			||||||
 | 
					     * @throws \BookStack\Exceptions\NotifyException
 | 
				
			||||||
 | 
					     * @throws \Illuminate\Contracts\Container\BindingResolutionException
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function delete(string $id)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        // TODO -
 | 
					        $book = Book::visible()->findOrFail($id);
 | 
				
			||||||
 | 
					        $this->checkOwnablePermission('book-delete', $book);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->bookRepo->destroy($book);
 | 
				
			||||||
 | 
					        Activity::addMessage('book_delete', $book->name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return response('', 204);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -8,6 +8,7 @@ class Image extends Ownable
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected $fillable = ['name'];
 | 
					    protected $fillable = ['name'];
 | 
				
			||||||
 | 
					    protected $hidden = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Get a thumbnail for this image.
 | 
					     * Get a thumbnail for this image.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,10 @@
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  "name": "My new book",
 | 
				
			||||||
 | 
					  "description": "This is a book created via the API",
 | 
				
			||||||
 | 
					  "created_by": 1,
 | 
				
			||||||
 | 
					  "updated_by": 1,
 | 
				
			||||||
 | 
					  "slug": "my-new-book",
 | 
				
			||||||
 | 
					  "updated_at": "2020-01-12 14:05:11",
 | 
				
			||||||
 | 
					  "created_at": "2020-01-12 14:05:11",
 | 
				
			||||||
 | 
					  "id": 15
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,27 @@
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  "data": [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "id": 1,
 | 
				
			||||||
 | 
					      "name": "BookStack User Guide",
 | 
				
			||||||
 | 
					      "slug": "bookstack-user-guide",
 | 
				
			||||||
 | 
					      "description": "This is a general guide on using BookStack on a day-to-day basis.",
 | 
				
			||||||
 | 
					      "created_at": "2019-05-05 21:48:46",
 | 
				
			||||||
 | 
					      "updated_at": "2019-12-11 20:57:31",
 | 
				
			||||||
 | 
					      "created_by": 1,
 | 
				
			||||||
 | 
					      "updated_by": 1,
 | 
				
			||||||
 | 
					      "image_id": 3
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "id": 2,
 | 
				
			||||||
 | 
					      "name": "Inventore inventore quia voluptatem.",
 | 
				
			||||||
 | 
					      "slug": "inventore-inventore-quia-voluptatem",
 | 
				
			||||||
 | 
					      "description": "Veniam nihil voluptas enim laborum corporis quos sint. Ab rerum voluptas ut iste voluptas magni quibusdam ut. Amet omnis enim voluptate neque facilis.",
 | 
				
			||||||
 | 
					      "created_at": "2019-05-05 22:10:14",
 | 
				
			||||||
 | 
					      "updated_at": "2019-12-11 20:57:23",
 | 
				
			||||||
 | 
					      "created_by": 4,
 | 
				
			||||||
 | 
					      "updated_by": 3,
 | 
				
			||||||
 | 
					      "image_id": 34
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  ],
 | 
				
			||||||
 | 
					  "total": 14
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,47 @@
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  "id": 16,
 | 
				
			||||||
 | 
					  "name": "My own book",
 | 
				
			||||||
 | 
					  "slug": "my-own-book",
 | 
				
			||||||
 | 
					  "description": "This is my own little book",
 | 
				
			||||||
 | 
					  "created_at": "2020-01-12 14:09:59",
 | 
				
			||||||
 | 
					  "updated_at": "2020-01-12 14:11:51",
 | 
				
			||||||
 | 
					  "created_by": {
 | 
				
			||||||
 | 
					    "id": 1,
 | 
				
			||||||
 | 
					    "name": "Admin",
 | 
				
			||||||
 | 
					    "created_at": "2019-05-05 21:15:13",
 | 
				
			||||||
 | 
					    "updated_at": "2019-12-16 12:18:37",
 | 
				
			||||||
 | 
					    "image_id": 48
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "updated_by": {
 | 
				
			||||||
 | 
					    "id": 1,
 | 
				
			||||||
 | 
					    "name": "Admin",
 | 
				
			||||||
 | 
					    "created_at": "2019-05-05 21:15:13",
 | 
				
			||||||
 | 
					    "updated_at": "2019-12-16 12:18:37",
 | 
				
			||||||
 | 
					    "image_id": 48
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "image_id": 452,
 | 
				
			||||||
 | 
					  "tags": [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "id": 13,
 | 
				
			||||||
 | 
					      "entity_id": 16,
 | 
				
			||||||
 | 
					      "entity_type": "BookStack\\Book",
 | 
				
			||||||
 | 
					      "name": "Category",
 | 
				
			||||||
 | 
					      "value": "Guide",
 | 
				
			||||||
 | 
					      "order": 0,
 | 
				
			||||||
 | 
					      "created_at": "2020-01-12 14:11:51",
 | 
				
			||||||
 | 
					      "updated_at": "2020-01-12 14:11:51"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  ],
 | 
				
			||||||
 | 
					  "cover": {
 | 
				
			||||||
 | 
					    "id": 452,
 | 
				
			||||||
 | 
					    "name": "sjovall_m117hUWMu40.jpg",
 | 
				
			||||||
 | 
					    "url": "http:\/\/bookstack.local\/uploads\/images\/cover_book\/2020-01\/sjovall_m117hUWMu40.jpg",
 | 
				
			||||||
 | 
					    "created_at": "2020-01-12 14:11:51",
 | 
				
			||||||
 | 
					    "updated_at": "2020-01-12 14:11:51",
 | 
				
			||||||
 | 
					    "created_by": 1,
 | 
				
			||||||
 | 
					    "updated_by": 1,
 | 
				
			||||||
 | 
					    "path": "\/uploads\/images\/cover_book\/2020-01\/sjovall_m117hUWMu40.jpg",
 | 
				
			||||||
 | 
					    "type": "cover_book",
 | 
				
			||||||
 | 
					    "uploaded_to": 16
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,11 @@
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  "id": 16,
 | 
				
			||||||
 | 
					  "name": "My own book",
 | 
				
			||||||
 | 
					  "slug": "my-own-book",
 | 
				
			||||||
 | 
					  "description": "This is my own little book - updated",
 | 
				
			||||||
 | 
					  "created_at": "2020-01-12 14:09:59",
 | 
				
			||||||
 | 
					  "updated_at": "2020-01-12 14:16:10",
 | 
				
			||||||
 | 
					  "created_by": 1,
 | 
				
			||||||
 | 
					  "updated_by": 1,
 | 
				
			||||||
 | 
					  "image_id": 452
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -2,11 +2,12 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Routes for the BookStack API.
 | 
					 * Routes for the BookStack API.
 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Routes have a uri prefix of /api/.
 | 
					 * Routes have a uri prefix of /api/.
 | 
				
			||||||
 | 
					 * Controllers are all within app/Http/Controllers/Api
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
// TODO - Authenticate middleware
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Route::get('books', 'BooksApiController@index');
 | 
					Route::get('books', 'BooksApiController@index');
 | 
				
			||||||
 | 
					Route::post('books', 'BooksApiController@create');
 | 
				
			||||||
 | 
					Route::get('books/{id}', 'BooksApiController@read');
 | 
				
			||||||
 | 
					Route::put('books/{id}', 'BooksApiController@update');
 | 
				
			||||||
 | 
					Route::delete('books/{id}', 'BooksApiController@delete');
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,87 @@
 | 
				
			||||||
 | 
					<?php namespace Tests;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use BookStack\Entities\Book;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ApiAuthTest extends TestCase
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    use TestsApi;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected $baseEndpoint = '/api/books';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function test_index_endpoint_returns_expected_book()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->actingAsApiEditor();
 | 
				
			||||||
 | 
					        $firstBook = Book::query()->orderBy('id', 'asc')->first();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $resp = $this->getJson($this->baseEndpoint . '?count=1&sort=+id');
 | 
				
			||||||
 | 
					        $resp->assertJson(['data' => [
 | 
				
			||||||
 | 
					            [
 | 
				
			||||||
 | 
					                'id' => $firstBook->id,
 | 
				
			||||||
 | 
					                'name' => $firstBook->name,
 | 
				
			||||||
 | 
					                'slug' => $firstBook->slug,
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        ]]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function test_create_endpoint()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->actingAsApiEditor();
 | 
				
			||||||
 | 
					        $details = [
 | 
				
			||||||
 | 
					            'name' => 'My API book',
 | 
				
			||||||
 | 
					            'description' => 'A book created via the API',
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $resp = $this->postJson($this->baseEndpoint, $details);
 | 
				
			||||||
 | 
					        $resp->assertStatus(200);
 | 
				
			||||||
 | 
					        $newItem = Book::query()->orderByDesc('id')->where('name', '=', $details['name'])->first();
 | 
				
			||||||
 | 
					        $resp->assertJson(array_merge($details, ['id' => $newItem->id, 'slug' => $newItem->slug]));
 | 
				
			||||||
 | 
					        $this->assertActivityExists('book_create', $newItem);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function test_read_endpoint()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->actingAsApiEditor();
 | 
				
			||||||
 | 
					        $book = Book::visible()->first();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $resp = $this->getJson($this->baseEndpoint . "/{$book->id}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $resp->assertStatus(200);
 | 
				
			||||||
 | 
					        $resp->assertJson([
 | 
				
			||||||
 | 
					            'id' => $book->id,
 | 
				
			||||||
 | 
					            'slug' => $book->slug,
 | 
				
			||||||
 | 
					            'created_by' => [
 | 
				
			||||||
 | 
					                'name' => $book->createdBy->name,
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            'updated_by' => [
 | 
				
			||||||
 | 
					                'name' => $book->createdBy->name,
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function test_update_endpoint()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->actingAsApiEditor();
 | 
				
			||||||
 | 
					        $book = Book::visible()->first();
 | 
				
			||||||
 | 
					        $details = [
 | 
				
			||||||
 | 
					            'name' => 'My updated API book',
 | 
				
			||||||
 | 
					            'description' => 'A book created via the API',
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $resp = $this->putJson($this->baseEndpoint . "/{$book->id}", $details);
 | 
				
			||||||
 | 
					        $book->refresh();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $resp->assertStatus(200);
 | 
				
			||||||
 | 
					        $resp->assertJson(array_merge($details, ['id' => $book->id, 'slug' => $book->slug]));
 | 
				
			||||||
 | 
					        $this->assertActivityExists('book_update', $book);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function test_delete_endpoint()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->actingAsApiEditor();
 | 
				
			||||||
 | 
					        $book = Book::visible()->first();
 | 
				
			||||||
 | 
					        $resp = $this->deleteJson($this->baseEndpoint . "/{$book->id}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $resp->assertStatus(204);
 | 
				
			||||||
 | 
					        $this->assertActivityExists('book_delete');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,6 @@
 | 
				
			||||||
<?php namespace Tests;
 | 
					<?php namespace Tests;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use BookStack\Entities\Entity;
 | 
				
			||||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
 | 
					use Illuminate\Foundation\Testing\DatabaseTransactions;
 | 
				
			||||||
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
 | 
					use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -60,4 +61,20 @@ abstract class TestCase extends BaseTestCase
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return TestResponse::fromBaseResponse($response);
 | 
					        return TestResponse::fromBaseResponse($response);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Assert that an activity entry exists of the given key.
 | 
				
			||||||
 | 
					     * Checks the activity belongs to the given entity if provided.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    protected function assertActivityExists(string $key, Entity $entity = null)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $detailsToCheck = ['key' => $key];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($entity) {
 | 
				
			||||||
 | 
					            $detailsToCheck['entity_type'] = $entity->getMorphClass();
 | 
				
			||||||
 | 
					            $detailsToCheck['entity_id'] = $entity->id;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->assertDatabaseHas('activities', $detailsToCheck);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue