mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-11-23 11:22:33 +01:00
Tweaked some styles and started automated testing. Fixes #11.
This commit is contained in:
parent
30d2edddda
commit
713827f941
@ -70,7 +70,7 @@ class BookController extends Controller
|
||||
$book->updated_by = Auth::user()->id;
|
||||
$book->save();
|
||||
Activity::add($book, 'book_create', $book->id);
|
||||
return redirect('/books');
|
||||
return redirect($book->getUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -65,7 +65,7 @@ class ChapterController extends Controller
|
||||
$chapter->updated_by = Auth::user()->id;
|
||||
$book->chapters()->save($chapter);
|
||||
Activity::add($chapter, 'chapter_create', $book->id);
|
||||
return redirect($book->getUrl());
|
||||
return redirect($chapter->getUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -35,6 +35,11 @@ class BookRepo
|
||||
return $this->book->where('slug', '=', $slug)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new book instance from request input.
|
||||
* @param $input
|
||||
* @return Book
|
||||
*/
|
||||
public function newFromInput($input)
|
||||
{
|
||||
return $this->book->fill($input);
|
||||
|
@ -64,6 +64,18 @@ return [
|
||||
'strict' => false,
|
||||
],
|
||||
|
||||
'mysql_testing' => [
|
||||
'driver' => 'mysql',
|
||||
'host' => 'localhost',
|
||||
'database' => 'bookstack-test',
|
||||
'username' => 'bookstack-test',
|
||||
'password' => 'bookstack-test',
|
||||
'charset' => 'utf8',
|
||||
'collation' => 'utf8_unicode_ci',
|
||||
'prefix' => '',
|
||||
'strict' => false,
|
||||
],
|
||||
|
||||
'pgsql' => [
|
||||
'driver' => 'pgsql',
|
||||
'host' => env('DB_HOST', 'localhost'),
|
||||
|
@ -13,9 +13,30 @@
|
||||
|
||||
$factory->define(Oxbow\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(Oxbow\Book::class, function ($faker) {
|
||||
return [
|
||||
'name' => $faker->sentence,
|
||||
'description' => $faker->paragraph
|
||||
];
|
||||
});
|
||||
|
||||
$factory->define(Oxbow\Chapter::class, function ($faker) {
|
||||
return [
|
||||
'name' => $faker->sentence,
|
||||
'description' => $faker->paragraph
|
||||
];
|
||||
});
|
||||
|
||||
$factory->define(Oxbow\Page::class, function ($faker) {
|
||||
return [
|
||||
'name' => $faker->sentence,
|
||||
'html' => '<p>' . implode('</p>', $faker->paragraphs(5)) . '</p>'
|
||||
];
|
||||
});
|
@ -24,5 +24,6 @@
|
||||
<env name="CACHE_DRIVER" value="array"/>
|
||||
<env name="SESSION_DRIVER" value="array"/>
|
||||
<env name="QUEUE_DRIVER" value="sync"/>
|
||||
<env name="DB_CONNECTION" value="mysql_testing"/>
|
||||
</php>
|
||||
</phpunit>
|
||||
|
@ -51,6 +51,17 @@ $button-border-radius: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.text-button {
|
||||
@extend .link;
|
||||
background-color: transparent;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: none;
|
||||
&:focus, &:active {
|
||||
outline: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.button-group {
|
||||
@include clearfix;
|
||||
.button, button[type="button"] {
|
||||
|
@ -43,11 +43,13 @@ h1, h2, h3, h4 {
|
||||
/*
|
||||
* Link styling
|
||||
*/
|
||||
a {
|
||||
a, .link {
|
||||
color: $primary;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
transition: color ease-in-out 80ms;
|
||||
font-family: $text;
|
||||
line-height: 1.6;
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
color: darken($primary, 20%);
|
||||
|
@ -309,8 +309,10 @@ h1, h2, h3, h4, h5, h6 {
|
||||
}
|
||||
|
||||
.faded {
|
||||
a {
|
||||
a, button, span {
|
||||
color: #666;
|
||||
}
|
||||
.text-button {
|
||||
opacity: 0.5;
|
||||
transition: all ease-in-out 120ms;
|
||||
&:hover {
|
||||
@ -324,12 +326,9 @@ h1, h2, h3, h4, h5, h6 {
|
||||
color: #000;
|
||||
font-size: 0.9em;
|
||||
background-color: rgba(21, 101, 192, 0.15);
|
||||
a, span {
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
|
||||
.breadcrumbs a, .action-buttons a {
|
||||
.breadcrumbs .text-button, .action-buttons .text-button {
|
||||
display: inline-block;
|
||||
padding: $-s;
|
||||
&:last-child {
|
||||
@ -340,7 +339,7 @@ h1, h2, h3, h4, h5, h6 {
|
||||
text-align: right;
|
||||
&.text-left {
|
||||
text-align: left;
|
||||
a {
|
||||
.text-button {
|
||||
padding-right: $-m;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
<div class="col-md-6 faded">
|
||||
<div class="action-buttons">
|
||||
@if($currentUser->can('book-create'))
|
||||
<a href="/books/create" class="text-pos"><i class="zmdi zmdi-plus"></i>Add new book</a>
|
||||
<a href="/books/create" class="text-pos text-button"><i class="zmdi zmdi-plus"></i>Add new book</a>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
@ -8,17 +8,17 @@
|
||||
<div class="col-md-12">
|
||||
<div class="action-buttons faded">
|
||||
@if($currentUser->can('page-create'))
|
||||
<a href="{{$book->getUrl() . '/page/create'}}" class="text-pos"><i class="zmdi zmdi-plus"></i> New Page</a>
|
||||
<a href="{{$book->getUrl() . '/page/create'}}" class="text-pos text-button"><i class="zmdi zmdi-plus"></i> New Page</a>
|
||||
@endif
|
||||
@if($currentUser->can('chapter-create'))
|
||||
<a href="{{$book->getUrl() . '/chapter/create'}}" class="text-pos"><i class="zmdi zmdi-plus"></i> New Chapter</a>
|
||||
<a href="{{$book->getUrl() . '/chapter/create'}}" class="text-pos text-button"><i class="zmdi zmdi-plus"></i> New Chapter</a>
|
||||
@endif
|
||||
@if($currentUser->can('book-update'))
|
||||
<a href="{{$book->getEditUrl()}}" class="text-primary"><i class="zmdi zmdi-edit"></i>Edit</a>
|
||||
<a href="{{ $book->getUrl() }}/sort" class="text-primary"><i class="zmdi zmdi-sort"></i>Sort</a>
|
||||
<a href="{{$book->getEditUrl()}}" class="text-primary text-button"><i class="zmdi zmdi-edit"></i>Edit</a>
|
||||
<a href="{{ $book->getUrl() }}/sort" class="text-primary text-button"><i class="zmdi zmdi-sort"></i>Sort</a>
|
||||
@endif
|
||||
@if($currentUser->can('book-delete'))
|
||||
<a href="{{ $book->getUrl() }}/delete" class="text-neg"><i class="zmdi zmdi-delete"></i>Delete</a>
|
||||
<a href="{{ $book->getUrl() }}/delete" class="text-neg text-button"><i class="zmdi zmdi-delete"></i>Delete</a>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
@ -13,5 +13,5 @@
|
||||
|
||||
<div class="form-group">
|
||||
<a href="{{ back()->getTargetUrl() }}" class="button muted">Cancel</a>
|
||||
<button type="submit" class="button pos">Save</button>
|
||||
<button type="submit" class="button pos">Save Chapter</button>
|
||||
</div>
|
||||
|
@ -7,19 +7,19 @@
|
||||
<div class="row">
|
||||
<div class="col-md-4 faded">
|
||||
<div class="breadcrumbs">
|
||||
<a href="{{$book->getUrl()}}" class="text-book"><i class="zmdi zmdi-book"></i>{{ $book->name }}</a>
|
||||
<a href="{{$book->getUrl()}}" class="text-book text-button"><i class="zmdi zmdi-book"></i>{{ $book->name }}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-8 faded">
|
||||
<div class="action-buttons">
|
||||
@if($currentUser->can('chapter-create'))
|
||||
<a href="{{$chapter->getUrl() . '/create-page'}}" class="text-pos"><i class="zmdi zmdi-plus"></i>New Page</a>
|
||||
<a href="{{$chapter->getUrl() . '/create-page'}}" class="text-pos text-button"><i class="zmdi zmdi-plus"></i>New Page</a>
|
||||
@endif
|
||||
@if($currentUser->can('chapter-update'))
|
||||
<a href="{{$chapter->getUrl() . '/edit'}}" class="text-primary"><i class="zmdi zmdi-edit"></i>Edit</a>
|
||||
<a href="{{$chapter->getUrl() . '/edit'}}" class="text-primary text-button"><i class="zmdi zmdi-edit"></i>Edit</a>
|
||||
@endif
|
||||
@if($currentUser->can('chapter-delete'))
|
||||
<a href="{{$chapter->getUrl() . '/delete'}}" class="text-neg"><i class="zmdi zmdi-delete"></i>Delete</a>
|
||||
<a href="{{$chapter->getUrl() . '/delete'}}" class="text-neg text-button"><i class="zmdi zmdi-delete"></i>Delete</a>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
@ -9,13 +9,13 @@
|
||||
<div class="row">
|
||||
<div class="col-md-4 faded">
|
||||
<div class="action-buttons text-left">
|
||||
<a onclick="$('body>header').slideToggle();" class="text-primary"><i class="zmdi zmdi-swap-vertical"></i>Toggle Header</a>
|
||||
<a onclick="$('body>header').slideToggle();" class="text-button text-primary"><i class="zmdi zmdi-swap-vertical"></i>Toggle Header</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-8 faded">
|
||||
<div class="action-buttons">
|
||||
<a href="{{ back()->getTargetUrl() }}" class="text-primary"><i class="zmdi zmdi-close"></i>Cancel</a>
|
||||
<a onclick="$(this).submitForm();" type="submit" class="text-pos"><i class="zmdi zmdi-floppy"></i>Save Page</a>
|
||||
<a href="{{ back()->getTargetUrl() }}" class="text-button text-primary"><i class="zmdi zmdi-close"></i>Cancel</a>
|
||||
<button type="submit" class="text-button text-pos"><i class="zmdi zmdi-floppy"></i>Save Page</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -7,7 +7,7 @@
|
||||
<div class="row">
|
||||
<div class="col-md-6 faded">
|
||||
<div class="breadcrumbs">
|
||||
<a href="{{$page->getUrl()}}" class="text-primary"><i class="zmdi zmdi-arrow-left"></i>Back to page</a>
|
||||
<a href="{{$page->getUrl()}}" class="text-primary text-button"><i class="zmdi zmdi-arrow-left"></i>Back to page</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 faded">
|
||||
|
@ -7,10 +7,10 @@
|
||||
<div class="row">
|
||||
<div class="col-md-6 faded">
|
||||
<div class="breadcrumbs">
|
||||
<a href="{{$book->getUrl()}}" class="text-book"><i class="zmdi zmdi-book"></i>{{ $book->name }}</a>
|
||||
<a href="{{$book->getUrl()}}" class="text-book text-button"><i class="zmdi zmdi-book"></i>{{ $book->name }}</a>
|
||||
@if($page->hasChapter())
|
||||
<span class="sep">»</span>
|
||||
<a href="{{ $page->chapter->getUrl() }}" class="text-chapter">
|
||||
<a href="{{ $page->chapter->getUrl() }}" class="text-chapter text-button">
|
||||
<i class="zmdi zmdi-collection-bookmark"></i>
|
||||
{{$page->chapter->name}}
|
||||
</a>
|
||||
@ -20,11 +20,11 @@
|
||||
<div class="col-md-6 faded">
|
||||
<div class="action-buttons">
|
||||
@if($currentUser->can('page-update'))
|
||||
<a href="{{$page->getUrl() . '/revisions'}}" class="text-primary"><i class="zmdi zmdi-replay"></i>Revisions</a>
|
||||
<a href="{{$page->getUrl() . '/edit'}}" class="text-primary" ><i class="zmdi zmdi-edit"></i>Edit</a>
|
||||
<a href="{{$page->getUrl() . '/revisions'}}" class="text-primary text-button"><i class="zmdi zmdi-replay"></i>Revisions</a>
|
||||
<a href="{{$page->getUrl() . '/edit'}}" class="text-primary text-button" ><i class="zmdi zmdi-edit"></i>Edit</a>
|
||||
@endif
|
||||
@if($currentUser->can('page-delete'))
|
||||
<a href="{{$page->getUrl() . '/delete'}}" class="text-neg"><i class="zmdi zmdi-delete"></i>Delete</a>
|
||||
<a href="{{$page->getUrl() . '/delete'}}" class="text-neg text-button"><i class="zmdi zmdi-delete"></i>Delete</a>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
@ -6,7 +6,7 @@
|
||||
@foreach($book->children() as $bookChild)
|
||||
<li class="list-item-{{ $bookChild->getName() }}">
|
||||
<a href="{{$bookChild->getUrl()}}" class="{{ $bookChild->getName() }} {{ $current->matches($bookChild)? 'selected' : '' }}">
|
||||
@if($bookChild->isA('chapter'))<i class="zmdi zmdi-collection-bookmark chapter-toggle"></i>@else <i class="zmdi zmdi-file-text"></i>@endif{{ $bookChild->name }}
|
||||
@if($bookChild->isA('chapter'))<i class="zmdi zmdi-collection-bookmark"></i>@else <i class="zmdi zmdi-file-text"></i>@endif{{ $bookChild->name }}
|
||||
</a>
|
||||
|
||||
@if($bookChild->isA('chapter') && count($bookChild->pages) > 0)
|
||||
|
@ -3,8 +3,8 @@
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12 setting-nav">
|
||||
<a href="/settings" @if($selected == 'settings') class="selected" @endif><i class="zmdi zmdi-settings"></i>Settings</a>
|
||||
<a href="/users" @if($selected == 'users') class="selected" @endif><i class="zmdi zmdi-accounts"></i>Users</a>
|
||||
<a href="/settings" @if($selected == 'settings') class="selected text-button" @endif><i class="zmdi zmdi-settings"></i>Settings</a>
|
||||
<a href="/users" @if($selected == 'users') class="selected text-button" @endif><i class="zmdi zmdi-accounts"></i>Users</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -9,7 +9,7 @@
|
||||
<div class="col-md-6"></div>
|
||||
<div class="col-md-6 faded">
|
||||
<div class="action-buttons">
|
||||
<a href="/users/{{$user->id}}/delete" class="text-neg"><i class="zmdi zmdi-delete"></i>Delete User</a>
|
||||
<a href="/users/{{$user->id}}/delete" class="text-neg text-button"><i class="zmdi zmdi-delete"></i>Delete User</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
32
tests/AuthTest.php
Normal file
32
tests/AuthTest.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
class AuthTest extends TestCase
|
||||
{
|
||||
|
||||
public function testAuthWorking()
|
||||
{
|
||||
$this->visit('/')
|
||||
->seePageIs('/login');
|
||||
}
|
||||
|
||||
public function testLogin()
|
||||
{
|
||||
$this->visit('/')
|
||||
->seePageIs('/login')
|
||||
->type('admin@admin.com', '#email')
|
||||
->type('password', '#password')
|
||||
->press('Sign In')
|
||||
->seePageIs('/')
|
||||
->see('BookStack');
|
||||
}
|
||||
|
||||
public function testLogout()
|
||||
{
|
||||
$this->asAdmin()
|
||||
->visit('/')
|
||||
->seePageIs('/')
|
||||
->visit('/logout')
|
||||
->visit('/')
|
||||
->seePageIs('/login');
|
||||
}
|
||||
}
|
121
tests/EntityTest.php
Normal file
121
tests/EntityTest.php
Normal file
@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
class EntityTest extends TestCase
|
||||
{
|
||||
|
||||
public function testEntityCreation()
|
||||
{
|
||||
|
||||
// Test Creation
|
||||
$book = $this->bookCreation();
|
||||
$chapter = $this->chapterCreation($book);
|
||||
$page = $this->pageCreation($chapter);
|
||||
|
||||
// Test Updating
|
||||
$book = $this->bookUpdate($book);
|
||||
|
||||
// Test Deletion
|
||||
$this->bookDelete($book);
|
||||
}
|
||||
|
||||
public function bookDelete(\Oxbow\Book $book)
|
||||
{
|
||||
$this->asAdmin()
|
||||
->visit($book->getUrl())
|
||||
// Check link works correctly
|
||||
->click('Delete')
|
||||
->seePageIs($book->getUrl() . '/delete')
|
||||
// Ensure the book name is show to user
|
||||
->see($book->name)
|
||||
->press('Confirm')
|
||||
->seePageIs('/books')
|
||||
->notSeeInDatabase('books', ['id' => $book->id]);
|
||||
}
|
||||
|
||||
public function bookUpdate(\Oxbow\Book $book)
|
||||
{
|
||||
$newName = $book->name . ' Updated';
|
||||
$this->asAdmin()
|
||||
// Go to edit screen
|
||||
->visit($book->getUrl() . '/edit')
|
||||
->see($book->name)
|
||||
// Submit new name
|
||||
->type($newName, '#name')
|
||||
->press('Save Book')
|
||||
// Check page url and text
|
||||
->seePageIs($book->getUrl() . '-updated')
|
||||
->see($newName);
|
||||
|
||||
return \Oxbow\Book::find($book->id);
|
||||
}
|
||||
|
||||
public function pageCreation($chapter)
|
||||
{
|
||||
$page = factory(\Oxbow\Page::class)->make([
|
||||
'name' => 'My First Page'
|
||||
]);
|
||||
|
||||
$this->asAdmin()
|
||||
// Navigate to page create form
|
||||
->visit($chapter->getUrl())
|
||||
->click('New Page')
|
||||
->seePageIs($chapter->getUrl() . '/create-page')
|
||||
// Fill out form
|
||||
->type($page->name, '#name')
|
||||
->type($page->html, '#html')
|
||||
->press('Save Page')
|
||||
// Check redirect and page
|
||||
->seePageIs($chapter->book->getUrl() . '/page/my-first-page')
|
||||
->see($page->name);
|
||||
|
||||
$page = \Oxbow\Page::where('slug', '=', 'my-first-page')->where('chapter_id', '=', $chapter->id)->first();
|
||||
return $page;
|
||||
}
|
||||
|
||||
public function chapterCreation(\Oxbow\Book $book)
|
||||
{
|
||||
$chapter = factory(\Oxbow\Chapter::class)->make([
|
||||
'name' => 'My First Chapter'
|
||||
]);
|
||||
|
||||
$this->asAdmin()
|
||||
// Navigate to chapter create page
|
||||
->visit($book->getUrl())
|
||||
->click('New Chapter')
|
||||
->seePageIs($book->getUrl() . '/chapter/create')
|
||||
// Fill out form
|
||||
->type($chapter->name, '#name')
|
||||
->type($chapter->description, '#description')
|
||||
->press('Save Chapter')
|
||||
// Check redirect and landing page
|
||||
->seePageIs($book->getUrl() . '/chapter/my-first-chapter')
|
||||
->see($chapter->name)->see($chapter->description);
|
||||
|
||||
$chapter = \Oxbow\Chapter::where('slug', '=', 'my-first-chapter')->where('book_id', '=', $book->id)->first();
|
||||
return $chapter;
|
||||
}
|
||||
|
||||
public function bookCreation()
|
||||
{
|
||||
$book = factory(\Oxbow\Book::class)->make([
|
||||
'name' => 'My First Book'
|
||||
]);
|
||||
$this->asAdmin()
|
||||
->visit('/books')
|
||||
// Choose to create a book
|
||||
->click('Add new book')
|
||||
->seePageIs('/books/create')
|
||||
// Fill out form & save
|
||||
->type($book->name, '#name')
|
||||
->type($book->description, '#description')
|
||||
->press('Save Book')
|
||||
// Check it redirects correctly
|
||||
->seePageIs('/books/my-first-book')
|
||||
->see($book->name)->see($book->description);
|
||||
|
||||
$book = \Oxbow\Book::where('slug', '=', 'my-first-book')->first();
|
||||
return $book;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Foundation\Testing\WithoutMiddleware;
|
||||
use Illuminate\Foundation\Testing\DatabaseMigrations;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
|
||||
class ExampleTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* A basic functional test example.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testBasicExample()
|
||||
{
|
||||
$this->visit('/')
|
||||
->see('Laravel 5');
|
||||
}
|
||||
}
|
@ -1,13 +1,19 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
|
||||
class TestCase extends Illuminate\Foundation\Testing\TestCase
|
||||
{
|
||||
|
||||
use DatabaseTransactions;
|
||||
|
||||
/**
|
||||
* The base URL to use while testing the application.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $baseUrl = 'http://localhost';
|
||||
private $admin;
|
||||
|
||||
/**
|
||||
* Creates the application.
|
||||
@ -22,4 +28,12 @@ class TestCase extends Illuminate\Foundation\Testing\TestCase
|
||||
|
||||
return $app;
|
||||
}
|
||||
|
||||
public function asAdmin()
|
||||
{
|
||||
if($this->admin === null) {
|
||||
$this->admin = \Oxbow\User::find(1);
|
||||
}
|
||||
return $this->actingAs($this->admin);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user