mirror of
https://github.com/BookStackApp/BookStack.git
synced 2025-11-06 00:50:36 +03:00
API: Built out tests for comment API endpoints
This commit is contained in:
@@ -50,8 +50,8 @@ class CommentRepo
|
||||
// Validate parent ID
|
||||
if ($parentId !== null) {
|
||||
$parentCommentExists = Comment::query()
|
||||
->where('entity_id', '=', $entity->id)
|
||||
->where('entity_type', '=', $entity->getMorphClass())
|
||||
->where('commentable_id', '=', $entity->id)
|
||||
->where('commentable_type', '=', $entity->getMorphClass())
|
||||
->where('local_id', '=', $parentId)
|
||||
->exists();
|
||||
if (!$parentCommentExists) {
|
||||
|
||||
@@ -23,9 +23,6 @@ class CommentApiController extends ApiController
|
||||
{
|
||||
// TODO - Add tree-style comment listing to page-show responses.
|
||||
|
||||
// TODO - Test visibility controls
|
||||
// TODO - Test permissions of each action
|
||||
|
||||
protected array $rules = [
|
||||
'create' => [
|
||||
'page_id' => ['required', 'integer'],
|
||||
@@ -34,7 +31,7 @@ class CommentApiController extends ApiController
|
||||
'content_ref' => ['string'],
|
||||
],
|
||||
'update' => [
|
||||
'html' => ['required', 'string'],
|
||||
'html' => ['string'],
|
||||
'archived' => ['boolean'],
|
||||
]
|
||||
];
|
||||
@@ -85,6 +82,7 @@ class CommentApiController extends ApiController
|
||||
public function read(string $id): JsonResponse
|
||||
{
|
||||
$comment = $this->commentRepo->getVisibleById(intval($id));
|
||||
$comment->load('createdBy', 'updatedBy');
|
||||
|
||||
$replies = $this->commentRepo->getQueryForVisible()
|
||||
->where('parent_id', '=', $comment->local_id)
|
||||
@@ -117,17 +115,19 @@ class CommentApiController extends ApiController
|
||||
$this->checkOwnablePermission(Permission::CommentUpdate, $comment);
|
||||
|
||||
$input = $this->validate($request, $this->rules()['update']);
|
||||
$hasHtml = isset($input['html']);
|
||||
|
||||
if (isset($input['archived'])) {
|
||||
$archived = $input['archived'];
|
||||
if ($archived) {
|
||||
$this->commentRepo->archive($comment, false);
|
||||
if ($input['archived']) {
|
||||
$this->commentRepo->archive($comment, !$hasHtml);
|
||||
} else {
|
||||
$this->commentRepo->unarchive($comment, false);
|
||||
$this->commentRepo->unarchive($comment, !$hasHtml);
|
||||
}
|
||||
}
|
||||
|
||||
$comment = $this->commentRepo->update($comment, $input['html']);
|
||||
if ($hasHtml) {
|
||||
$comment = $this->commentRepo->update($comment, $input['html']);
|
||||
}
|
||||
|
||||
return response()->json($comment);
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ class Comment extends Model implements Loggable, OwnableInterface
|
||||
*/
|
||||
public function entity(): MorphTo
|
||||
{
|
||||
return $this->morphTo('entity');
|
||||
return $this->morphTo('commentable');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
namespace Activity;
|
||||
|
||||
use BookStack\Activity\ActivityType;
|
||||
use BookStack\Facades\Activity;
|
||||
use BookStack\Activity\Models\Comment;
|
||||
use BookStack\Permissions\Permission;
|
||||
use Tests\Api\TestsApi;
|
||||
use Tests\TestCase;
|
||||
|
||||
@@ -13,31 +13,238 @@ class CommentsApiTest extends TestCase
|
||||
|
||||
public function test_endpoint_permission_controls()
|
||||
{
|
||||
// TODO
|
||||
$user = $this->users->editor();
|
||||
$this->permissions->grantUserRolePermissions($user, [Permission::CommentDeleteAll, Permission::CommentUpdateAll]);
|
||||
|
||||
$page = $this->entities->page();
|
||||
$comment = Comment::factory()->make();
|
||||
$page->comments()->save($comment);
|
||||
$this->actingAsForApi($user);
|
||||
|
||||
$actions = [
|
||||
['GET', '/api/comments'],
|
||||
['GET', "/api/comments/{$comment->id}"],
|
||||
['POST', "/api/comments"],
|
||||
['PUT', "/api/comments/{$comment->id}"],
|
||||
['DELETE', "/api/comments/{$comment->id}"],
|
||||
];
|
||||
|
||||
foreach ($actions as [$method, $endpoint]) {
|
||||
$resp = $this->call($method, $endpoint);
|
||||
$this->assertNotPermissionError($resp);
|
||||
}
|
||||
|
||||
$comment = Comment::factory()->make();
|
||||
$page->comments()->save($comment);
|
||||
$this->getJson("/api/comments")->assertSee(['id' => $comment->id]);
|
||||
|
||||
$this->permissions->removeUserRolePermissions($user, [
|
||||
Permission::CommentDeleteAll, Permission::CommentDeleteOwn,
|
||||
Permission::CommentUpdateAll, Permission::CommentUpdateOwn,
|
||||
Permission::CommentCreateAll
|
||||
]);
|
||||
|
||||
$this->assertPermissionError($this->json('delete', "/api/comments/{$comment->id}"));
|
||||
$this->assertPermissionError($this->json('put', "/api/comments/{$comment->id}"));
|
||||
$this->assertPermissionError($this->json('post', "/api/comments"));
|
||||
$this->assertNotPermissionError($this->json('get', "/api/comments/{$comment->id}"));
|
||||
|
||||
$this->permissions->disableEntityInheritedPermissions($page);
|
||||
$this->json('get', "/api/comments/{$comment->id}")->assertStatus(404);
|
||||
$this->getJson("/api/comments")->assertDontSee(['id' => $comment->id]);
|
||||
}
|
||||
|
||||
public function test_index()
|
||||
{
|
||||
// TODO
|
||||
$page = $this->entities->page();
|
||||
Comment::query()->delete();
|
||||
|
||||
$comments = Comment::factory()->count(10)->make();
|
||||
$page->comments()->saveMany($comments);
|
||||
|
||||
$firstComment = $comments->first();
|
||||
$resp = $this->actingAsApiEditor()->getJson('/api/comments');
|
||||
$resp->assertJson([
|
||||
'data' => [
|
||||
[
|
||||
'id' => $firstComment->id,
|
||||
'commentable_id' => $page->id,
|
||||
'commentable_type' => 'page',
|
||||
'parent_id' => null,
|
||||
'local_id' => $firstComment->local_id,
|
||||
],
|
||||
],
|
||||
]);
|
||||
$resp->assertJsonCount(10, 'data');
|
||||
$resp->assertJson(['total' => 10]);
|
||||
|
||||
$filtered = $this->getJson("/api/comments?filter[id]={$firstComment->id}");
|
||||
$filtered->assertJsonCount(1, 'data');
|
||||
$filtered->assertJson(['total' => 1]);
|
||||
}
|
||||
|
||||
public function test_create()
|
||||
{
|
||||
// TODO
|
||||
$page = $this->entities->page();
|
||||
|
||||
$resp = $this->actingAsApiEditor()->postJson('/api/comments', [
|
||||
'page_id' => $page->id,
|
||||
'html' => '<p>My wonderful comment</p>',
|
||||
'content_ref' => 'test-content-ref',
|
||||
]);
|
||||
$resp->assertOk();
|
||||
$id = $resp->json('id');
|
||||
|
||||
$this->assertDatabaseHas('comments', [
|
||||
'id' => $id,
|
||||
'commentable_id' => $page->id,
|
||||
'commentable_type' => 'page',
|
||||
'html' => '<p>My wonderful comment</p>',
|
||||
]);
|
||||
|
||||
$comment = Comment::query()->findOrFail($id);
|
||||
$this->assertIsInt($comment->local_id);
|
||||
|
||||
$reply = $this->actingAsApiEditor()->postJson('/api/comments', [
|
||||
'page_id' => $page->id,
|
||||
'html' => '<p>My wonderful reply</p>',
|
||||
'content_ref' => 'test-content-ref',
|
||||
'reply_to' => $comment->local_id,
|
||||
]);
|
||||
$reply->assertOk();
|
||||
|
||||
$this->assertDatabaseHas('comments', [
|
||||
'id' => $reply->json('id'),
|
||||
'commentable_id' => $page->id,
|
||||
'commentable_type' => 'page',
|
||||
'html' => '<p>My wonderful reply</p>',
|
||||
'parent_id' => $comment->local_id,
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_read()
|
||||
{
|
||||
// TODO
|
||||
$page = $this->entities->page();
|
||||
$user = $this->users->viewer();
|
||||
$comment = Comment::factory()->make([
|
||||
'html' => '<p>A lovely comment <script>hello</script></p>',
|
||||
'created_by' => $user->id,
|
||||
'updated_by' => $user->id,
|
||||
]);
|
||||
$page->comments()->save($comment);
|
||||
$comment->refresh();
|
||||
$reply = Comment::factory()->make([
|
||||
'parent_id' => $comment->local_id,
|
||||
'html' => '<p>A lovely<script>angry</script>reply</p>',
|
||||
]);
|
||||
$page->comments()->save($reply);
|
||||
|
||||
$resp = $this->actingAsApiEditor()->getJson("/api/comments/{$comment->id}");
|
||||
$resp->assertJson([
|
||||
'id' => $comment->id,
|
||||
'commentable_id' => $page->id,
|
||||
'commentable_type' => 'page',
|
||||
'html' => '<p>A lovely comment </p>',
|
||||
'archived' => false,
|
||||
'created_by' => [
|
||||
'id' => $user->id,
|
||||
'name' => $user->name,
|
||||
],
|
||||
'updated_by' => [
|
||||
'id' => $user->id,
|
||||
'name' => $user->name,
|
||||
],
|
||||
'replies' => [
|
||||
[
|
||||
'id' => $reply->id,
|
||||
'html' => '<p>A lovelyreply</p>'
|
||||
]
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_update()
|
||||
{
|
||||
// TODO
|
||||
$page = $this->entities->page();
|
||||
$user = $this->users->editor();
|
||||
$this->permissions->grantUserRolePermissions($user, [Permission::CommentUpdateAll]);
|
||||
$comment = Comment::factory()->make([
|
||||
'html' => '<p>A lovely comment</p>',
|
||||
'created_by' => $this->users->viewer()->id,
|
||||
'updated_by' => $this->users->viewer()->id,
|
||||
'parent_id' => null,
|
||||
]);
|
||||
$page->comments()->save($comment);
|
||||
|
||||
$this->actingAsForApi($user)->putJson("/api/comments/{$comment->id}", [
|
||||
'html' => '<p>A lovely updated comment</p>',
|
||||
])->assertOk();
|
||||
|
||||
$this->assertDatabaseHas('comments', [
|
||||
'id' => $comment->id,
|
||||
'html' => '<p>A lovely updated comment</p>',
|
||||
'archived' => 0,
|
||||
]);
|
||||
|
||||
$this->putJson("/api/comments/{$comment->id}", [
|
||||
'archived' => true,
|
||||
]);
|
||||
|
||||
$this->assertDatabaseHas('comments', [
|
||||
'id' => $comment->id,
|
||||
'html' => '<p>A lovely updated comment</p>',
|
||||
'archived' => 1,
|
||||
]);
|
||||
|
||||
$this->putJson("/api/comments/{$comment->id}", [
|
||||
'archived' => false,
|
||||
'html' => '<p>A lovely updated again comment</p>',
|
||||
]);
|
||||
|
||||
$this->assertDatabaseHas('comments', [
|
||||
'id' => $comment->id,
|
||||
'html' => '<p>A lovely updated again comment</p>',
|
||||
'archived' => 0,
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_update_cannot_archive_replies()
|
||||
{
|
||||
$page = $this->entities->page();
|
||||
$user = $this->users->editor();
|
||||
$this->permissions->grantUserRolePermissions($user, [Permission::CommentUpdateAll]);
|
||||
$comment = Comment::factory()->make([
|
||||
'html' => '<p>A lovely comment</p>',
|
||||
'created_by' => $this->users->viewer()->id,
|
||||
'updated_by' => $this->users->viewer()->id,
|
||||
'parent_id' => 90,
|
||||
]);
|
||||
$page->comments()->save($comment);
|
||||
|
||||
$resp = $this->actingAsForApi($user)->putJson("/api/comments/{$comment->id}", [
|
||||
'archived' => true,
|
||||
]);
|
||||
|
||||
$this->assertEquals($this->errorResponse('Only top-level comments can be archived.', 400), $resp->json());
|
||||
$this->assertDatabaseHas('comments', [
|
||||
'id' => $comment->id,
|
||||
'archived' => 0,
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_destroy()
|
||||
{
|
||||
// TODO
|
||||
$page = $this->entities->page();
|
||||
$user = $this->users->editor();
|
||||
$this->permissions->grantUserRolePermissions($user, [Permission::CommentDeleteAll]);
|
||||
$comment = Comment::factory()->make([
|
||||
'html' => '<p>A lovely comment</p>',
|
||||
]);
|
||||
$page->comments()->save($comment);
|
||||
|
||||
$this->actingAsForApi($user)->deleteJson("/api/comments/{$comment->id}")->assertStatus(204);
|
||||
$this->assertDatabaseMissing('comments', [
|
||||
'id' => $comment->id,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,7 +199,7 @@ abstract class TestCase extends BaseTestCase
|
||||
{
|
||||
if ($response->status() === 403 && $response instanceof JsonResponse) {
|
||||
$errMessage = $response->getData(true)['error']['message'] ?? '';
|
||||
return $errMessage === 'You do not have permission to perform the requested action.';
|
||||
return str_contains($errMessage, 'do not have permission');
|
||||
}
|
||||
|
||||
return $response->status() === 302
|
||||
|
||||
Reference in New Issue
Block a user