From 7d02f77e6764175d2375a2b55e366b9beaba31a3 Mon Sep 17 00:00:00 2001
From: Abijeet <abijeetpatro@gmail.com>
Date: Tue, 13 Jun 2017 02:31:17 +0530
Subject: [PATCH] #47 - Added more test cases to test the APIs and permission
 for comments.

---
 database/factories/ModelFactory.php           |   2 +-
 ...017_01_01_130541_create_comments_table.php |  47 +++++++-
 tests/Entity/CommentTest.php                  | 111 ++++++++++++++++++
 tests/Permissions/RolesTest.php               | 106 +++++++++++++++++
 4 files changed, 264 insertions(+), 2 deletions(-)
 create mode 100644 tests/Entity/CommentTest.php

diff --git a/database/factories/ModelFactory.php b/database/factories/ModelFactory.php
index b5bb32c11..b03e34b9b 100644
--- a/database/factories/ModelFactory.php
+++ b/database/factories/ModelFactory.php
@@ -77,7 +77,7 @@ $factory->define(BookStack\Comment::class, function($faker) {
     $html = '<p>' . $text. '</p>';
     return [
         'html' => $html,
-        'text' => '#' . $text,
+        'text' => $text,
         'active' => 1
     ];
 });
\ No newline at end of file
diff --git a/database/migrations/2017_01_01_130541_create_comments_table.php b/database/migrations/2017_01_01_130541_create_comments_table.php
index 8aa99eea4..f4ece31a7 100644
--- a/database/migrations/2017_01_01_130541_create_comments_table.php
+++ b/database/migrations/2017_01_01_130541_create_comments_table.php
@@ -17,7 +17,7 @@ class CreateCommentsTable extends Migration
             return;
         }
         Schema::create('comments', function (Blueprint $table) {
-            $table->increments('id')->unsigned();                       
+            $table->increments('id')->unsigned();
             $table->integer('page_id')->unsigned();
             $table->longText('text')->nullable();
             $table->longText('html')->nullable();
@@ -45,6 +45,51 @@ class CreateCommentsTable extends Migration
                     'permission_id' => $permissionId
                 ]);
             }
+
+            // Get roles with permissions we need to change
+            /*
+            $editorRole = DB::table('roles')->where('name', '=', 'editor')->first();
+            if (!empty($editorRole)) {
+                $editorRoleId = $editorRole->id;
+                // Create & attach new entity permissions
+                $ops = ['Create All', 'Create Own', 'Update Own', 'Delete Own'];
+                $entity = 'Comment';
+                foreach ($ops as $op) {
+                    $permissionId = DB::table('role_permissions')->insertGetId([
+                        'name' => strtolower($entity) . '-' . strtolower(str_replace(' ', '-', $op)),
+                        'display_name' => $op . ' ' . $entity . 's',
+                        'created_at' => \Carbon\Carbon::now()->toDateTimeString(),
+                        'updated_at' => \Carbon\Carbon::now()->toDateTimeString()
+                    ]);
+                    DB::table('permission_role')->insert([
+                        'role_id' => $editorRoleId,
+                        'permission_id' => $permissionId
+                    ]);
+                }
+            }
+
+            // Get roles with permissions we need to change
+            $viewerRole = DB::table('roles')->where('name', '=', 'viewer')->first();
+            if (!empty($viewerRole)) {
+                $viewerRoleId = $viewerRole->id;
+                // Create & attach new entity permissions
+                $ops = ['Create All'];
+                $entity = 'Comment';
+                foreach ($ops as $op) {
+                    $permissionId = DB::table('role_permissions')->insertGetId([
+                        'name' => strtolower($entity) . '-' . strtolower(str_replace(' ', '-', $op)),
+                        'display_name' => $op . ' ' . $entity . 's',
+                        'created_at' => \Carbon\Carbon::now()->toDateTimeString(),
+                        'updated_at' => \Carbon\Carbon::now()->toDateTimeString()
+                    ]);
+                    DB::table('permission_role')->insert([
+                        'role_id' => $viewerRoleId,
+                        'permission_id' => $permissionId
+                    ]);
+                }
+            }
+            */
+
         });
     }
 
diff --git a/tests/Entity/CommentTest.php b/tests/Entity/CommentTest.php
new file mode 100644
index 000000000..86eb31213
--- /dev/null
+++ b/tests/Entity/CommentTest.php
@@ -0,0 +1,111 @@
+<?php namespace Tests;
+
+use BookStack\Page;
+use BookStack\Comment;
+
+class CommentTest extends BrowserKitTest
+{
+
+    public function test_add_comment()
+    {
+        $this->asAdmin();
+        $page = $this->getPage();
+
+        $this->addComment($page);
+    }
+
+    public function test_comment_reply()
+    {
+        $this->asAdmin();
+        $page = $this->getPage();
+
+        // add a normal comment
+        $createdComment = $this->addComment($page);
+
+        // reply to the added comment
+        $this->addComment($page, $createdComment['id']);
+    }
+
+    public function test_comment_edit()
+    {
+        $this->asAdmin();
+        $page = $this->getPage();
+
+        $createdComment = $this->addComment($page);
+        $comment = [
+            'id' => $createdComment['id'],
+            'page_id' => $createdComment['page_id']
+        ];
+        $this->updateComment($comment);
+    }
+
+    public function test_comment_delete()
+    {
+        $this->asAdmin();
+        $page = $this->getPage();
+
+        $createdComment = $this->addComment($page);
+
+        $this->deleteComment($createdComment['id']);
+    }
+
+    private function getPage() {
+        $page = Page::first();
+        return $page;
+    }
+
+
+    private function addComment($page, $parentCommentId = null) {
+        $comment = factory(Comment::class)->make();
+        $url = "/ajax/page/$page->id/comment/";
+        $request = [
+            'text' => $comment->text,
+            'html' => $comment->html
+        ];
+        if (!empty($parentCommentId)) {
+            $request['parent_id'] = $parentCommentId;
+        }
+        $this->call('POST', $url, $request);
+
+        $createdComment = $this->checkResponse();
+        return $createdComment;
+    }
+
+    private function updateComment($comment) {
+        $tmpComment = factory(Comment::class)->make();
+        $url = '/ajax/page/' . $comment['page_id'] . '/comment/ ' . $comment['id'];
+         $request = [
+            'text' => $tmpComment->text,
+            'html' => $tmpComment->html
+        ];
+
+        $this->call('PUT', $url, $request);
+
+        $updatedComment = $this->checkResponse();
+        return $updatedComment;
+    }
+
+    private function deleteComment($commentId) {
+        //  Route::delete('/ajax/comment/{id}', 'CommentController@destroy');
+        $url = '/ajax/comment/' . $commentId;
+        $this->call('DELETE', $url);
+
+        $deletedComment = $this->checkResponse();
+        return $deletedComment;
+    }
+
+    private function checkResponse() {
+        $expectedResp = [
+            'status' => 'success'
+        ];
+
+        $this->assertResponseOk();
+        $this->seeJsonContains($expectedResp);
+
+        $resp = $this->decodeResponseJson();
+        $createdComment = $resp['comment'];
+        $this->assertArrayHasKey('id', $createdComment);
+
+        return $createdComment;
+    }
+}
diff --git a/tests/Permissions/RolesTest.php b/tests/Permissions/RolesTest.php
index 83d1b98a8..9d054fe0b 100644
--- a/tests/Permissions/RolesTest.php
+++ b/tests/Permissions/RolesTest.php
@@ -620,4 +620,110 @@ class RolesTest extends BrowserKitTest
             ->dontSeeInDatabase('images', ['id' => $image->id]);
     }
 
+    public function test_comment_create_permission () {
+        $ownPage = $this->createEntityChainBelongingToUser($this->user)['page'];
+
+        $this->actingAs($this->user)->addComment($ownPage);
+
+        $this->assertResponseStatus(403);
+
+        $this->giveUserPermissions($this->user, ['comment-create-all']);
+
+        $this->actingAs($this->user)->addComment($ownPage);
+        $this->assertResponseOk(200)->seeJsonContains(['status' => 'success']);
+    }
+
+
+    public function test_comment_update_own_permission () {
+        $ownPage = $this->createEntityChainBelongingToUser($this->user)['page'];
+        $this->giveUserPermissions($this->user, ['comment-create-all']);
+        $comment = $this->actingAs($this->user)->addComment($ownPage);
+
+        // no comment-update-own
+        $this->actingAs($this->user)->updateComment($ownPage, $comment['id']);
+        $this->assertResponseStatus(403);
+
+        $this->giveUserPermissions($this->user, ['comment-update-own']);
+
+        // now has comment-update-own
+        $this->actingAs($this->user)->updateComment($ownPage, $comment['id']);
+        $this->assertResponseOk()->seeJsonContains(['status' => 'success']);
+    }
+
+    public function test_comment_update_all_permission () {
+        $ownPage = $this->createEntityChainBelongingToUser($this->user)['page'];
+        $comment = $this->asAdmin()->addComment($ownPage);
+
+        // no comment-update-all
+        $this->actingAs($this->user)->updateComment($ownPage, $comment['id']);
+        $this->assertResponseStatus(403);
+
+        $this->giveUserPermissions($this->user, ['comment-update-all']);
+
+        // now has comment-update-all
+        $this->actingAs($this->user)->updateComment($ownPage, $comment['id']);
+        $this->assertResponseOk()->seeJsonContains(['status' => 'success']);
+    }
+
+    public function test_comment_delete_own_permission () {
+        $ownPage = $this->createEntityChainBelongingToUser($this->user)['page'];
+        $this->giveUserPermissions($this->user, ['comment-create-all']);
+        $comment = $this->actingAs($this->user)->addComment($ownPage);
+
+        // no comment-delete-own
+        $this->actingAs($this->user)->deleteComment($comment['id']);
+        $this->assertResponseStatus(403);
+
+        $this->giveUserPermissions($this->user, ['comment-delete-own']);
+
+        // now has comment-update-own
+        $this->actingAs($this->user)->deleteComment($comment['id']);
+        $this->assertResponseOk()->seeJsonContains(['status' => 'success']);
+    }
+
+    public function test_comment_delete_all_permission () {
+        $ownPage = $this->createEntityChainBelongingToUser($this->user)['page'];
+        $comment = $this->asAdmin()->addComment($ownPage);
+
+        // no comment-delete-all
+        $this->actingAs($this->user)->deleteComment($comment['id']);
+        $this->assertResponseStatus(403);
+
+        $this->giveUserPermissions($this->user, ['comment-delete-all']);
+
+        // now has comment-delete-all
+        $this->actingAs($this->user)->deleteComment($comment['id']);
+        $this->assertResponseOk()->seeJsonContains(['status' => 'success']);
+    }
+
+    private function addComment($page) {
+        $comment = factory(\BookStack\Comment::class)->make();
+        $url = "/ajax/page/$page->id/comment/";
+        $request = [
+            'text' => $comment->text,
+            'html' => $comment->html
+        ];
+
+        $this->json('POST', $url, $request);
+        $resp = $this->decodeResponseJson();
+        return $resp['comment'];
+
+    }
+
+    private function updateComment($page, $commentId) {
+        $comment = factory(\BookStack\Comment::class)->make();
+        $url = "/ajax/page/$page->id/comment/$commentId";
+        $request = [
+            'text' => $comment->text,
+            'html' => $comment->html
+        ];
+
+        return $this->json('PUT', $url, $request);
+    }
+
+    private function deleteComment($commentId) {
+         $url = '/ajax/comment/' . $commentId;
+         return $this->json('DELETE', $url);
+    }
+
 }