From 55abf7be241e0a81f1460da70fcebb7d8530d950 Mon Sep 17 00:00:00 2001
From: Dan Brown <ssddanbrown@googlemail.com>
Date: Mon, 30 Dec 2019 20:48:23 +0000
Subject: [PATCH] Added tests to cover API config and listing code

---
 tests/Api/ApiConfigTest.php  | 47 +++++++++++++++++++++++++++
 tests/Api/ApiListingTest.php | 61 ++++++++++++++++++++++++++++++++++++
 tests/TestsApi.php           | 21 +++++++++++--
 3 files changed, 126 insertions(+), 3 deletions(-)
 create mode 100644 tests/Api/ApiConfigTest.php
 create mode 100644 tests/Api/ApiListingTest.php

diff --git a/tests/Api/ApiConfigTest.php b/tests/Api/ApiConfigTest.php
new file mode 100644
index 000000000..99b063c69
--- /dev/null
+++ b/tests/Api/ApiConfigTest.php
@@ -0,0 +1,47 @@
+<?php
+
+namespace Tests;
+
+use BookStack\Auth\Permissions\RolePermission;
+use Carbon\Carbon;
+
+class ApiAuthTest extends TestCase
+{
+    use TestsApi;
+
+    protected $endpoint = '/api/books';
+
+    public function test_default_item_count_reflected_in_listing_requests()
+    {
+        $this->actingAsApiEditor();
+
+        config()->set(['api.default_item_count' => 5]);
+        $resp = $this->get($this->endpoint);
+        $resp->assertJsonCount(5, 'data');
+
+        config()->set(['api.default_item_count' => 1]);
+        $resp = $this->get($this->endpoint);
+        $resp->assertJsonCount(1, 'data');
+    }
+
+    public function test_default_item_count_does_not_limit_count_param()
+    {
+        $this->actingAsApiEditor();
+        config()->set(['api.default_item_count' => 1]);
+        $resp = $this->get($this->endpoint . '?count=5');
+        $resp->assertJsonCount(5, 'data');
+    }
+
+    public function test_max_item_count_limits_listing_requests()
+    {
+        $this->actingAsApiEditor();
+
+        config()->set(['api.max_item_count' => 2]);
+        $resp = $this->get($this->endpoint);
+        $resp->assertJsonCount(2, 'data');
+
+        $resp = $this->get($this->endpoint . '?count=5');
+        $resp->assertJsonCount(2, 'data');
+    }
+
+}
\ No newline at end of file
diff --git a/tests/Api/ApiListingTest.php b/tests/Api/ApiListingTest.php
new file mode 100644
index 000000000..70d1140d7
--- /dev/null
+++ b/tests/Api/ApiListingTest.php
@@ -0,0 +1,61 @@
+<?php
+
+namespace Tests;
+
+use BookStack\Auth\Permissions\RolePermission;
+use BookStack\Entities\Book;
+use Carbon\Carbon;
+
+class ApiAuthTest extends TestCase
+{
+    use TestsApi;
+
+    protected $endpoint = '/api/books';
+
+    public function test_count_parameter_limits_responses()
+    {
+        $this->actingAsApiEditor();
+        $bookCount = min(Book::visible()->count(), 100);
+
+        $resp = $this->get($this->endpoint);
+        $resp->assertJsonCount($bookCount, 'data');
+
+        $resp = $this->get($this->endpoint . '?count=1');
+        $resp->assertJsonCount(1, 'data');
+    }
+
+    public function test_offset_parameter()
+    {
+        $this->actingAsApiEditor();
+        $books = Book::visible()->orderBy('id')->take(3)->get();
+
+        $resp = $this->get($this->endpoint . '?count=1');
+        $resp->assertJsonMissing(['name' => $books[1]->name ]);
+
+        $resp = $this->get($this->endpoint . '?count=1&offset=1000');
+        $resp->assertJsonCount(0, 'data');
+    }
+
+    public function test_sort_parameter()
+    {
+        $this->actingAsApiEditor();
+
+        $sortChecks = [
+            '-id' => Book::visible()->orderBy('id', 'desc')->first(),
+            '+name' => Book::visible()->orderBy('name', 'asc')->first(),
+            'name' => Book::visible()->orderBy('name', 'asc')->first(),
+            '-name' => Book::visible()->orderBy('name', 'desc')->first()
+        ];
+
+        foreach ($sortChecks as $sortOption => $result) {
+            $resp = $this->get($this->endpoint . '?count=1&sort=' . $sortOption);
+            $resp->assertJson(['data' => [
+                [
+                    'id' => $result->id,
+                    'name' => $result->name,
+                ]
+            ]]);
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/tests/TestsApi.php b/tests/TestsApi.php
index 4afcbdf22..0bb10a4cc 100644
--- a/tests/TestsApi.php
+++ b/tests/TestsApi.php
@@ -8,12 +8,27 @@ trait TestsApi
     protected $apiTokenId = 'apitoken';
     protected $apiTokenSecret = 'password';
 
-    protected function errorResponse(string $messge, int $code)
+    /**
+     * Set the API editor role as the current user via the API driver.
+     */
+    protected function actingAsApiEditor()
     {
-        return ["error" => ["code" => $code, "message" => $messge]];
+        $this->actingAs($this->getEditor(), 'api');
+        return $this;
     }
 
-    protected function apiAuthHeader()
+    /**
+     * Format the given items into a standardised error format.
+     */
+    protected function errorResponse(string $message, int $code): array
+    {
+        return ["error" => ["code" => $code, "message" => $message]];
+    }
+
+    /**
+     * Get an approved API auth header.
+     */
+    protected function apiAuthHeader(): array
     {
         return [
             "Authorization" => "Token {$this->apiTokenId}:{$this->apiTokenSecret}"