From 62338e4a8fc3401dad8b01adf165f34a63ebe907 Mon Sep 17 00:00:00 2001
From: Dan Brown
Date: Sun, 29 Nov 2015 17:33:25 +0000
Subject: [PATCH] Added further tests, Fixed speed_update issues, improved
search result query count
---
app/Chapter.php | 3 +-
app/Entity.php | 18 +++++--
app/Http/Controllers/BookController.php | 6 ++-
app/Http/Controllers/ChapterController.php | 12 ++---
app/Repos/BookRepo.php | 2 +-
database/factories/ModelFactory.php | 20 ++++----
.../2015_11_26_221857_add_entity_indexes.php | 40 ++++++++--------
readme.md | 12 +++++
resources/views/base.blade.php | 4 +-
resources/views/books/sort-box.blade.php | 2 +-
resources/views/books/sort.blade.php | 2 +-
tests/EntityTest.php | 47 ++++++++++++++++++-
12 files changed, 115 insertions(+), 53 deletions(-)
diff --git a/app/Chapter.php b/app/Chapter.php
index c3001b69b..b6c8684a0 100644
--- a/app/Chapter.php
+++ b/app/Chapter.php
@@ -3,7 +3,6 @@
class Chapter extends Entity
{
-
protected $fillable = ['name', 'description', 'priority', 'book_id'];
public function book()
@@ -18,7 +17,7 @@ class Chapter extends Entity
public function getUrl()
{
- $bookSlug = isset($this->bookSlug) ? $this->bookSlug : $this->book->slug;
+ $bookSlug = $this->getAttribute('bookSlug') ? $this->getAttribute('bookSlug') : $this->book->slug;
return '/books/' . $bookSlug. '/chapter/' . $this->slug;
}
diff --git a/app/Entity.php b/app/Entity.php
index 1a8b02a4b..68c773592 100644
--- a/app/Entity.php
+++ b/app/Entity.php
@@ -69,19 +69,18 @@ abstract class Entity extends Model
* @param $type
* @return bool
*/
- public function isA($type)
+ public static function isA($type)
{
- return $this->getName() === strtolower($type);
+ return static::getName() === strtolower($type);
}
/**
* Gets the class name.
* @return string
*/
- public function getName()
+ public static function getName()
{
- $fullClassName = get_class($this);
- return strtolower(array_slice(explode('\\', $fullClassName), -1, 1)[0]);
+ return strtolower(array_slice(explode('\\', static::class), -1, 1)[0]);
}
/**
@@ -102,6 +101,15 @@ abstract class Entity extends Model
foreach ($wheres as $whereTerm) {
$search->where($whereTerm[0], $whereTerm[1], $whereTerm[2]);
}
+
+ if (!static::isA('book')) {
+ $search = $search->with('book');
+ }
+
+ if(static::isA('page')) {
+ $search = $search->with('chapter');
+ }
+
return $search->get();
}
diff --git a/app/Http/Controllers/BookController.php b/app/Http/Controllers/BookController.php
index c4173730d..6b2d6928d 100644
--- a/app/Http/Controllers/BookController.php
+++ b/app/Http/Controllers/BookController.php
@@ -150,14 +150,16 @@ class BookController extends Controller
{
$this->checkPermission('book-update');
$book = $this->bookRepo->getBySlug($bookSlug);
+ $bookChildren = $this->bookRepo->getChildren($book);
$books = $this->bookRepo->getAll();
- return view('books/sort', ['book' => $book, 'current' => $book, 'books' => $books]);
+ return view('books/sort', ['book' => $book, 'current' => $book, 'books' => $books, 'bookChildren' => $bookChildren]);
}
public function getSortItem($bookSlug)
{
$book = $this->bookRepo->getBySlug($bookSlug);
- return view('books/sort-box', ['book' => $book]);
+ $bookChildren = $this->bookRepo->getChildren($book);
+ return view('books/sort-box', ['book' => $book, 'bookChildren' => $bookChildren]);
}
/**
diff --git a/app/Http/Controllers/ChapterController.php b/app/Http/Controllers/ChapterController.php
index 42ae11355..1fe1e8b3e 100644
--- a/app/Http/Controllers/ChapterController.php
+++ b/app/Http/Controllers/ChapterController.php
@@ -33,7 +33,6 @@ class ChapterController extends Controller
/**
* Show the form for creating a new chapter.
- *
* @param $bookSlug
* @return Response
*/
@@ -46,7 +45,6 @@ class ChapterController extends Controller
/**
* Store a newly created chapter in storage.
- *
* @param $bookSlug
* @param Request $request
* @return Response
@@ -62,8 +60,8 @@ class ChapterController extends Controller
$chapter = $this->chapterRepo->newFromInput($request->all());
$chapter->slug = $this->chapterRepo->findSuitableSlug($chapter->name, $book->id);
$chapter->priority = $this->bookRepo->getNewPriority($book);
- $chapter->created_by = Auth::user()->id;
- $chapter->updated_by = Auth::user()->id;
+ $chapter->created_by = auth()->user()->id;
+ $chapter->updated_by = auth()->user()->id;
$book->chapters()->save($chapter);
Activity::add($chapter, 'chapter_create', $book->id);
return redirect($chapter->getUrl());
@@ -71,7 +69,6 @@ class ChapterController extends Controller
/**
* Display the specified chapter.
- *
* @param $bookSlug
* @param $chapterSlug
* @return Response
@@ -87,7 +84,6 @@ class ChapterController extends Controller
/**
* Show the form for editing the specified chapter.
- *
* @param $bookSlug
* @param $chapterSlug
* @return Response
@@ -102,7 +98,6 @@ class ChapterController extends Controller
/**
* Update the specified chapter in storage.
- *
* @param Request $request
* @param $bookSlug
* @param $chapterSlug
@@ -115,7 +110,7 @@ class ChapterController extends Controller
$chapter = $this->chapterRepo->getBySlug($chapterSlug, $book->id);
$chapter->fill($request->all());
$chapter->slug = $this->chapterRepo->findSuitableSlug($chapter->name, $book->id, $chapter->id);
- $chapter->updated_by = Auth::user()->id;
+ $chapter->updated_by = auth()->user()->id;
$chapter->save();
Activity::add($chapter, 'chapter_update', $book->id);
return redirect($chapter->getUrl());
@@ -137,7 +132,6 @@ class ChapterController extends Controller
/**
* Remove the specified chapter from storage.
- *
* @param $bookSlug
* @param $chapterSlug
* @return Response
diff --git a/app/Repos/BookRepo.php b/app/Repos/BookRepo.php
index 112971a27..9be77defe 100644
--- a/app/Repos/BookRepo.php
+++ b/app/Repos/BookRepo.php
@@ -141,7 +141,7 @@ class BookRepo
*/
public function getNewPriority($book)
{
- $lastElem = $book->children()->pop();
+ $lastElem = $this->getChildren($book)->pop();
return $lastElem ? $lastElem->priority + 1 : 0;
}
diff --git a/database/factories/ModelFactory.php b/database/factories/ModelFactory.php
index 31c7a3716..e0f155087 100644
--- a/database/factories/ModelFactory.php
+++ b/database/factories/ModelFactory.php
@@ -13,33 +13,35 @@
$factory->define(BookStack\User::class, function ($faker) {
return [
- 'name' => $faker->name,
- 'email' => $faker->email,
- 'password' => str_random(10),
+ 'name' => $faker->name,
+ 'email' => $faker->email,
+ 'password' => str_random(10),
'remember_token' => str_random(10),
];
});
$factory->define(BookStack\Book::class, function ($faker) {
return [
- 'name' => $faker->sentence,
- 'slug' => str_random(10),
+ 'name' => $faker->sentence,
+ 'slug' => str_random(10),
'description' => $faker->paragraph
];
});
$factory->define(BookStack\Chapter::class, function ($faker) {
return [
- 'name' => $faker->sentence,
- 'slug' => str_random(10),
+ 'name' => $faker->sentence,
+ 'slug' => str_random(10),
'description' => $faker->paragraph
];
});
$factory->define(BookStack\Page::class, function ($faker) {
+ $html = '' . implode('
', $faker->paragraphs(5)) . '
';
return [
'name' => $faker->sentence,
- 'slug' => str_random(10),
- 'html' => '' . implode('
', $faker->paragraphs(5)) . ''
+ 'slug' => str_random(10),
+ 'html' => $html,
+ 'text' => strip_tags($html)
];
});
diff --git a/database/migrations/2015_11_26_221857_add_entity_indexes.php b/database/migrations/2015_11_26_221857_add_entity_indexes.php
index 4e68dd68e..30f978cad 100644
--- a/database/migrations/2015_11_26_221857_add_entity_indexes.php
+++ b/database/migrations/2015_11_26_221857_add_entity_indexes.php
@@ -54,36 +54,36 @@ class AddEntityIndexes extends Migration
public function down()
{
Schema::table('books', function (Blueprint $table) {
- $table->dropIndex('slug');
- $table->dropIndex('created_by');
- $table->dropIndex('updated_by');
+ $table->dropIndex('books_slug_index');
+ $table->dropIndex('books_created_by_index');
+ $table->dropIndex('books_updated_by_index');
});
Schema::table('pages', function (Blueprint $table) {
- $table->dropIndex('slug');
- $table->dropIndex('book_id');
- $table->dropIndex('chapter_id');
- $table->dropIndex('priority');
- $table->dropIndex('created_by');
- $table->dropIndex('updated_by');
+ $table->dropIndex('pages_slug_index');
+ $table->dropIndex('pages_book_id_index');
+ $table->dropIndex('pages_chapter_id_index');
+ $table->dropIndex('pages_priority_index');
+ $table->dropIndex('pages_created_by_index');
+ $table->dropIndex('pages_updated_by_index');
});
Schema::table('page_revisions', function (Blueprint $table) {
- $table->dropIndex('page_id');
+ $table->dropIndex('page_revisions_page_id_index');
});
Schema::table('chapters', function (Blueprint $table) {
- $table->dropIndex('slug');
- $table->dropIndex('book_id');
- $table->dropIndex('priority');
- $table->dropIndex('created_by');
- $table->dropIndex('updated_by');
+ $table->dropIndex('chapters_slug_index');
+ $table->dropIndex('chapters_book_id_index');
+ $table->dropIndex('chapters_priority_index');
+ $table->dropIndex('chapters_created_by_index');
+ $table->dropIndex('chapters_updated_by_index');
});
Schema::table('activities', function (Blueprint $table) {
- $table->dropIndex('book_id');
- $table->dropIndex('user_id');
- $table->dropIndex('entity_id');
+ $table->dropIndex('activities_book_id_index');
+ $table->dropIndex('activities_user_id_index');
+ $table->dropIndex('activities_entity_id_index');
});
Schema::table('views', function (Blueprint $table) {
- $table->dropIndex('user_id');
- $table->dropIndex('entity_id');
+ $table->dropIndex('views_user_id_index');
+ $table->dropIndex('views_viewable_id_index');
});
}
}
diff --git a/readme.md b/readme.md
index 227c6210a..d2791f6e4 100644
--- a/readme.md
+++ b/readme.md
@@ -55,6 +55,18 @@ location / {
}
```
+## Testing
+
+BookStack has many integration tests that use Laravel's built-in testing capabilities which makes use of PHPUnit. To use you will need PHPUnit installed and accessible via command line. There is a `mysql_testing` database defined within the app config which is what is used by PHPUnit. This database is set with the following database name, user name and password defined as `bookstack-test`. You will have to create that database and credentials before testing.
+
+The testing database will also need migrating and seeding beforehand. This can be done with the following commands:
+
+```
+php artisan migrate --database=mysql_testing
+php artisan db:seed --class=DummyContentSeeder --database=mysql_testing
+```
+
+Once done you can run `phpunit` in the application root directory to run all tests.
## License
diff --git a/resources/views/base.blade.php b/resources/views/base.blade.php
index 6bbe434b4..f9dc81fa3 100644
--- a/resources/views/base.blade.php
+++ b/resources/views/base.blade.php
@@ -47,8 +47,8 @@
diff --git a/resources/views/books/sort-box.blade.php b/resources/views/books/sort-box.blade.php
index 1af2d1a42..768a9f608 100644
--- a/resources/views/books/sort-box.blade.php
+++ b/resources/views/books/sort-box.blade.php
@@ -1,7 +1,7 @@
{{ $book->name }}
- @foreach($book->children() as $bookChild)
+ @foreach($bookChildren as $bookChild)
-
{{ $bookChild->name }}
@if($bookChild->isA('chapter'))
diff --git a/resources/views/books/sort.blade.php b/resources/views/books/sort.blade.php
index 5fe278128..efdc04cf0 100644
--- a/resources/views/books/sort.blade.php
+++ b/resources/views/books/sort.blade.php
@@ -7,7 +7,7 @@
- @include('books/sort-box', ['book' => $book])
+ @include('books/sort-box', ['book' => $book, 'bookChildren' => $bookChildren])
diff --git a/tests/EntityTest.php b/tests/EntityTest.php
index 493f99cac..7cc2d640f 100644
--- a/tests/EntityTest.php
+++ b/tests/EntityTest.php
@@ -51,6 +51,34 @@ class EntityTest extends TestCase
return \BookStack\Book::find($book->id);
}
+ public function testBookSortPageShows()
+ {
+ $books = \BookStack\Book::all();
+ $bookToSort = $books[0];
+ $this->asAdmin()
+ ->visit($bookToSort->getUrl())
+ ->click('Sort')
+ ->seePageIs($bookToSort->getUrl() . '/sort')
+ ->seeStatusCode(200)
+ ->see($bookToSort->name)
+ // Ensure page shows other books
+ ->see($books[1]->name);
+ }
+
+ public function testBookSortItemReturnsBookContent()
+ {
+ $books = \BookStack\Book::all();
+ $bookToSort = $books[0];
+ $firstPage = $bookToSort->pages[0];
+ $firstChapter = $bookToSort->chapters[0];
+ $this->asAdmin()
+ ->visit($bookToSort->getUrl() . '/sort-item')
+ // Ensure book details are returned
+ ->see($bookToSort->name)
+ ->see($firstPage->name)
+ ->see($firstChapter->name);
+ }
+
public function pageCreation($chapter)
{
$page = factory(\BookStack\Page::class)->make([
@@ -118,12 +146,29 @@ class EntityTest extends TestCase
// Ensure duplicate names are given different slugs
$this->asAdmin()
->visit('/books/create')
- ->submitForm('Save Book', $book->toArray())
+ ->type($book->name, '#name')
+ ->type($book->description, '#description')
+ ->press('Save Book')
->seePageIs('/books/my-first-book-2');
$book = \BookStack\Book::where('slug', '=', 'my-first-book')->first();
return $book;
}
+ public function testPageSearch()
+ {
+ $book = \BookStack\Book::all()->first();
+ $page = $book->pages->first();
+
+ $this->asAdmin()
+ ->visit('/')
+ ->type($page->name, 'term')
+ ->press('header-search-box-button')
+ ->see('Search Results')
+ ->see($page->name)
+ ->click($page->name)
+ ->seePageIs($page->getUrl());
+ }
+
}