]> BookStack Code Mirror - bookstack/commitdiff
Cleaned tests up, Started LDAP tests, Created LDAP wrapper
authorDan Brown <redacted>
Fri, 15 Jan 2016 23:21:47 +0000 (23:21 +0000)
committerDan Brown <redacted>
Fri, 15 Jan 2016 23:21:47 +0000 (23:21 +0000)
15 files changed:
.env.example
app/Http/Controllers/Auth/AuthController.php
app/Http/Middleware/Authenticate.php
app/Http/routes.php
app/Providers/LdapUserProvider.php
app/Services/Ldap.php [new file with mode: 0644]
app/Services/LdapService.php
config/services.php
resources/views/public.blade.php
tests/ActivityTrackingTest.php
tests/Auth/AuthTest.php [moved from tests/AuthTest.php with 78% similarity]
tests/Auth/LdapTest.php [new file with mode: 0644]
tests/Auth/SocialAuthTest.php [moved from tests/SocialAuthTest.php with 82% similarity]
tests/EntityTest.php
tests/PublicViewTest.php

index 00d230bff4b06ebfaf3f860478b2e380ee61791d..d32d96c0d9dcba332829df3eac4ca80c3809b9bc 100644 (file)
@@ -36,6 +36,14 @@ APP_URL=http://bookstack.dev
 # External services such as Gravatar
 DISABLE_EXTERNAL_SERVICES=false
 
+# LDAP Settings
+LDAP_SERVER=false
+LDAP_BASE_DN=false
+LDAP_DN=false
+LDAP_PASS=false
+LDAP_USER_FILTER=false
+LDAP_VERSION=false
+
 # Mail settings
 MAIL_DRIVER=smtp
 MAIL_HOST=localhost
index 21abfb24c84950675f725c9ae2a7d104007ac573..d601b4985f9469fedded73b32907ab58420fb02b 100644 (file)
@@ -118,17 +118,20 @@ class AuthController extends Controller
      */
     protected function authenticated(Request $request, Authenticatable $user)
     {
-        if(!$user->exists && $user->email === null && !$request->has('email')) {
+        // Explicitly log them out for now if they do no exist.
+        if (!$user->exists) auth()->logout($user);
+
+        if (!$user->exists && $user->email === null && !$request->has('email')) {
             $request->flash();
             session()->flash('request-email', true);
             return redirect('/login');
         }
 
-        if(!$user->exists && $user->email === null && $request->has('email')) {
+        if (!$user->exists && $user->email === null && $request->has('email')) {
             $user->email = $request->get('email');
         }
 
-        if(!$user->exists) {
+        if (!$user->exists) {
             $user->save();
             $this->userRepo->attachDefaultRole($user);
             auth()->login($user);
index ebd830ffefb4a6a953934410fc06523798f0f301..ad804d0d86b15e16fb6c2bb6a553d7f4b29401ab 100644 (file)
@@ -38,6 +38,7 @@ class Authenticate
         if(auth()->check() && auth()->user()->email_confirmed == false) {
             return redirect()->guest('/register/confirm/awaiting');
         }
+
         if ($this->auth->guest() && !Setting::get('app-public')) {
             if ($request->ajax()) {
                 return response('Unauthorized.', 401);
index aedfca9bce9521f23741df2933dde82aae0669a1..23d4c33ab6cc876c233a40e1e66fb0f08fe61d64 100644 (file)
@@ -1,11 +1,5 @@
 <?php
 
-Route::get('/test', function() {
-    // TODO - remove this
-    $service = new \BookStack\Services\LdapService();
-    dd($service->getUserDetails('ksmith'));
-});
-
 // Authenticated routes...
 Route::group(['middleware' => 'auth'], function () {
 
index 98cfc8340cbe55b2fde188afb0d0f3946c1b8932..30fa739c265803f79af50e1def9b856fdf675a80 100644 (file)
@@ -86,8 +86,10 @@ class LdapUserProvider implements UserProvider
      */
     public function updateRememberToken(Authenticatable $user, $token)
     {
-        $user->setRememberToken($token);
-        $user->save();
+        if ($user->exists) {
+            $user->setRememberToken($token);
+            $user->save();
+        }
     }
 
     /**
@@ -113,6 +115,7 @@ class LdapUserProvider implements UserProvider
         $model->name = $userDetails['name'];
         $model->external_auth_id = $userDetails['uid'];
         $model->email = $userDetails['email'];
+        $model->email_confirmed = true;
         return $model;
     }
 
diff --git a/app/Services/Ldap.php b/app/Services/Ldap.php
new file mode 100644 (file)
index 0000000..cfefbb4
--- /dev/null
@@ -0,0 +1,86 @@
+<?php namespace BookStack\Services;
+
+
+/**
+ * Class Ldap
+ * An object-orientated thin abstraction wrapper for common PHP LDAP functions.
+ * Allows the standard LDAP functions to be mocked for testing.
+ * @package BookStack\Services
+ */
+class Ldap
+{
+
+    /**
+     * Connect to a LDAP server.
+     * @param string $hostName
+     * @param int    $port
+     * @return resource
+     */
+    public function connect($hostName, $port)
+    {
+        return ldap_connect($hostName, $port);
+    }
+
+    /**
+     * Set the value of a LDAP option for the given connection.
+     * @param resource $ldapConnection
+     * @param int $option
+     * @param mixed $value
+     * @return bool
+     */
+    public function setOption($ldapConnection, $option, $value)
+    {
+        return ldap_set_option($ldapConnection, $option, $value);
+    }
+
+    /**
+     * Search LDAP tree using the provided filter.
+     * @param resource   $ldapConnection
+     * @param string     $baseDn
+     * @param string     $filter
+     * @param array|null $attributes
+     * @return resource
+     */
+    public function search($ldapConnection, $baseDn, $filter, array $attributes = null)
+    {
+        return ldap_search($ldapConnection, $baseDn, $filter, $attributes);
+    }
+
+    /**
+     * Get entries from an ldap search result.
+     * @param resource $ldapConnection
+     * @param resource $ldapSearchResult
+     * @return array
+     */
+    public function getEntries($ldapConnection, $ldapSearchResult)
+    {
+        return ldap_get_entries($ldapConnection, $ldapSearchResult);
+    }
+
+    /**
+     * Search and get entries immediately.
+     * @param resource   $ldapConnection
+     * @param string     $baseDn
+     * @param string     $filter
+     * @param array|null $attributes
+     * @return resource
+     */
+    public function searchAndGetEntries($ldapConnection, $baseDn, $filter, array $attributes = null)
+    {
+        $search = $this->search($ldapConnection, $baseDn, $filter, $attributes);
+        return $this->getEntries($ldapConnection, $search);
+    }
+
+    /**
+     * Bind to LDAP directory.
+     * @param resource $ldapConnection
+     * @param string   $bindRdn
+     * @param string   $bindPassword
+     * @return bool
+     */
+    public function bind($ldapConnection, $bindRdn = null, $bindPassword = null)
+    {
+        return ldap_bind($ldapConnection, $bindRdn, $bindPassword);
+    }
+
+}
\ No newline at end of file
index cd80290e48b39a1c90b718c2b4e884b6a1f23686..d33f8c378fdb1fc87d2878d2dfda3fff40efcb4e 100644 (file)
@@ -4,10 +4,27 @@
 use BookStack\Exceptions\LdapException;
 use Illuminate\Contracts\Auth\Authenticatable;
 
+/**
+ * Class LdapService
+ * Handles any app-specific LDAP tasks.
+ * @package BookStack\Services
+ */
 class LdapService
 {
 
+    protected $ldap;
     protected $ldapConnection;
+    protected $config;
+
+    /**
+     * LdapService constructor.
+     * @param Ldap $ldap
+     */
+    public function __construct(Ldap $ldap)
+    {
+        $this->ldap = $ldap;
+        $this->config = config('services.ldap');
+    }
 
     /**
      * Get the details of a user from LDAP using the given username.
@@ -21,17 +38,16 @@ class LdapService
         $ldapConnection = $this->getConnection();
 
         // Find user
-        $userFilter = $this->buildFilter(config('services.ldap.user_filter'), ['user' => $userName]);
-        $baseDn = config('services.ldap.base_dn');
-        $ldapSearch = ldap_search($ldapConnection, $baseDn, $userFilter, ['cn', 'uid', 'dn', 'mail']);
-        $users = ldap_get_entries($ldapConnection, $ldapSearch);
+        $userFilter = $this->buildFilter($this->config['user_filter'], ['user' => $userName]);
+        $baseDn = $this->config['base_dn'];
+        $users = $this->ldap->searchAndGetEntries($ldapConnection, $baseDn, $userFilter, ['cn', 'uid', 'dn', 'mail']);
         if ($users['count'] === 0) return null;
 
         $user = $users[0];
         return [
-            'uid'  => $user['uid'][0],
-            'name' => $user['cn'][0],
-            'dn'   => $user['dn'],
+            'uid'   => $user['uid'][0],
+            'name'  => $user['cn'][0],
+            'dn'    => $user['dn'],
             'email' => (isset($user['mail'])) ? $user['mail'][0] : null
         ];
     }
@@ -50,7 +66,12 @@ class LdapService
         if ($ldapUser['uid'] !== $user->external_auth_id) return false;
 
         $ldapConnection = $this->getConnection();
-        $ldapBind = @ldap_bind($ldapConnection, $ldapUser['dn'], $password);
+        try {
+            $ldapBind = $this->ldap->bind($ldapConnection, $ldapUser['dn'], $password);
+        } catch (\ErrorException $e) {
+            $ldapBind = false;
+        }
+
         return $ldapBind;
     }
 
@@ -62,14 +83,14 @@ class LdapService
      */
     protected function bindSystemUser($connection)
     {
-        $ldapDn = config('services.ldap.dn');
-        $ldapPass = config('services.ldap.pass');
+        $ldapDn = $this->config['dn'];
+        $ldapPass = $this->config['pass'];
 
         $isAnonymous = ($ldapDn === false || $ldapPass === false);
         if ($isAnonymous) {
-            $ldapBind = ldap_bind($connection);
+            $ldapBind = $this->ldap->bind($connection);
         } else {
-            $ldapBind = ldap_bind($connection, $ldapDn, $ldapPass);
+            $ldapBind = $this->ldap->bind($connection, $ldapDn, $ldapPass);
         }
 
         if (!$ldapBind) throw new LdapException('LDAP access failed using ' . $isAnonymous ? ' anonymous bind.' : ' given dn & pass details');
@@ -86,20 +107,22 @@ class LdapService
         if ($this->ldapConnection !== null) return $this->ldapConnection;
 
         // Check LDAP extension in installed
-        if (!function_exists('ldap_connect')) {
+        if (!function_exists('ldap_connect') && config('app.env') !== 'testing') {
             throw new LdapException('LDAP PHP extension not installed');
         }
 
         // Get port from server string if specified.
-        $ldapServer = explode(':', config('services.ldap.server'));
-        $ldapConnection = ldap_connect($ldapServer[0], count($ldapServer) > 1 ? $ldapServer[1] : 389);
+        $ldapServer = explode(':', $this->config['server']);
+        $ldapConnection = $this->ldap->connect($ldapServer[0], count($ldapServer) > 1 ? $ldapServer[1] : 389);
 
         if ($ldapConnection === false) {
             throw new LdapException('Cannot connect to ldap server, Initial connection failed');
         }
 
         // Set any required options
-        ldap_set_option($ldapConnection, LDAP_OPT_PROTOCOL_VERSION, 3); // TODO - make configurable
+        if ($this->config['version']) {
+            $this->ldap->setOption($ldapConnection, LDAP_OPT_PROTOCOL_VERSION, $this->config['version']);
+        }
 
         $this->ldapConnection = $ldapConnection;
         return $this->ldapConnection;
@@ -107,7 +130,7 @@ class LdapService
 
     /**
      * Build a filter string by injecting common variables.
-     * @param       $filterString
+     * @param string $filterString
      * @param array $attrs
      * @return string
      */
index 08c2f3217b15a25fcdb2b0dba7bada2793f9c1f5..d71ff4a26d27a8987f11835e4472dc82c96865df 100644 (file)
@@ -54,7 +54,8 @@ return [
         'dn' => env('LDAP_DN', false),
         'pass' => env('LDAP_PASS', false),
         'base_dn' => env('LDAP_BASE_DN', false),
-        'user_filter' => env('LDAP_USER_FILTER', '(&(uid=${user}))')
+        'user_filter' => env('LDAP_USER_FILTER', '(&(uid=${user}))'),
+        'version' => env('LDAP_VERSION', false)
     ]
 
 ];
index 52c287987c5d4730644be34b6111ae21b587d82a..d34c490a7db0ac9d1ad657388c888fd84cbbcff0 100644 (file)
@@ -5,19 +5,19 @@
 
     <!-- Meta -->
     <meta name="viewport" content="width=device-width">
+    <meta name="token" content="{{ csrf_token() }}">
     <meta charset="utf-8">
 
     <!-- Styles and Fonts -->
     <link rel="stylesheet" href="{{ versioned_asset('css/styles.css') }}">
     <link rel="stylesheet" media="print" href="{{ versioned_asset('css/print-styles.css') }}">
-    <link href='//fonts.googleapis.com/css?family=Roboto:400,400italic,500,500italic,700,700italic,300italic,100,300' rel='stylesheet' type='text/css'>
     <link rel="stylesheet" href="/libs/material-design-iconic-font/css/material-design-iconic-font.min.css">
 
     <!-- Scripts -->
-    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
+    <script src="/libs/jquery/jquery.min.js?version=2.1.4"></script>
 
 </head>
-<body class="@yield('body-class')" id="app">
+<body class="@yield('body-class')" ng-app="bookStack">
 
 @include('partials/notifications')
 
                         @yield('header-buttons')
                     </div>
                     @if(isset($signedIn) && $signedIn)
-                        <img class="avatar" src="{{$currentUser->getAvatar(30)}}" alt="{{ $currentUser->name }}">
-                        <div class="dropdown-container" data-dropdown>
-                                <span class="user-name" data-dropdown-toggle>
-                                    {{ $currentUser->name }} <i class="zmdi zmdi-caret-down"></i>
+                        <div class="dropdown-container" dropdown>
+                                <span class="user-name" dropdown-toggle>
+                                    <img class="avatar" src="{{$currentUser->getAvatar(30)}}" alt="{{ $currentUser->name }}">
+                                    <span class="name" ng-non-bindable>{{ $currentUser->name }}</span> <i class="zmdi zmdi-caret-down"></i>
                                 </span>
                             <ul>
+                                <li>
+                                    <a href="/users/{{$currentUser->id}}" class="text-primary"><i class="zmdi zmdi-edit zmdi-hc-lg"></i>Edit Profile</a>
+                                </li>
                                 <li>
                                     <a href="/logout" class="text-neg"><i class="zmdi zmdi-run zmdi-hc-lg"></i>Logout</a>
                                 </li>
index 8a237f880d56c2504f7daa020b5bbe64461bff8e..8ee20ab6bcb76039c8d6bc4f81fa07035fb4a8c3 100644 (file)
@@ -7,7 +7,7 @@ use Illuminate\Foundation\Testing\DatabaseTransactions;
 class ActivityTrackingTest extends TestCase
 {
 
-    public function testRecentlyViewedBooks()
+    public function test_recently_viewed_books()
     {
         $books = \BookStack\Book::all()->take(10);
 
@@ -21,7 +21,7 @@ class ActivityTrackingTest extends TestCase
             ->seeInElement('#recents', $books[1]->name);
     }
 
-    public function testPopularBooks()
+    public function test_popular_books()
     {
         $books = \BookStack\Book::all()->take(10);
 
similarity index 78%
rename from tests/AuthTest.php
rename to tests/Auth/AuthTest.php
index 3faae6506e9a1fb1e1bdea9719530c742a5230ad..022dc14fb9b7e45e0b48288bf0ef4bf7037e53aa 100644 (file)
@@ -5,23 +5,19 @@ use BookStack\EmailConfirmation;
 class AuthTest extends TestCase
 {
 
-    public function testAuthWorking()
+    public function test_auth_working()
     {
         $this->visit('/')
             ->seePageIs('/login');
     }
 
-    public function testLogin()
+    public function test_login()
     {
-        $this->visit('/')
-            ->seePageIs('/login');
-
         $this->login('[email protected]', 'password')
-            ->seePageIs('/')
-            ->see('BookStack');
+            ->seePageIs('/');
     }
 
-    public function testPublicViewing()
+    public function test_public_viewing()
     {
         $settings = app('BookStack\Services\SettingService');
         $settings->put('app-public', 'true');
@@ -30,7 +26,7 @@ class AuthTest extends TestCase
             ->see('Sign In');
     }
 
-    public function testRegistrationShowing()
+    public function test_registration_showing()
     {
         // Ensure registration form is showing
         $this->setSettings(['registration-enabled' => 'true']);
@@ -40,7 +36,7 @@ class AuthTest extends TestCase
             ->seePageIs('/register');
     }
 
-    public function testNormalRegistration()
+    public function test_normal_registration()
     {
         // Set settings and get user instance
         $this->setSettings(['registration-enabled' => 'true']);
@@ -58,7 +54,8 @@ class AuthTest extends TestCase
             ->seeInDatabase('users', ['name' => $user->name, 'email' => $user->email]);
     }
 
-    public function testConfirmedRegistration()
+
+    public function test_confirmed_registration()
     {
         // Set settings and get user instance
         $this->setSettings(['registration-enabled' => 'true', 'registration-confirmation' => 'true']);
@@ -102,7 +99,32 @@ class AuthTest extends TestCase
             ->seeInDatabase('users', ['name' => $user->name, 'email' => $user->email, 'email_confirmed' => true]);
     }
 
-    public function testUserCreation()
+    public function test_restricted_registration()
+    {
+        $this->setSettings(['registration-enabled' => 'true', 'registration-confirmation' => 'true', 'registration-restrict' => 'example.com']);
+        $user = factory(\BookStack\User::class)->make();
+        // Go through registration process
+        $this->visit('/register')
+            ->type($user->name, '#name')
+            ->type($user->email, '#email')
+            ->type($user->password, '#password')
+            ->press('Create Account')
+            ->seePageIs('/register')
+            ->dontSeeInDatabase('users', ['email' => $user->email])
+            ->see('That email domain does not have access to this application');
+
+        $user->email = '[email protected]';
+
+        $this->visit('/register')
+            ->type($user->name, '#name')
+            ->type($user->email, '#email')
+            ->type($user->password, '#password')
+            ->press('Create Account')
+            ->seePageIs('/register/confirm')
+            ->seeInDatabase('users', ['name' => $user->name, 'email' => $user->email, 'email_confirmed' => false]);
+    }
+
+    public function test_user_creation()
     {
         $user = factory(\BookStack\User::class)->make();
 
@@ -120,7 +142,7 @@ class AuthTest extends TestCase
             ->see($user->name);
     }
 
-    public function testUserUpdating()
+    public function test_user_updating()
     {
         $user = \BookStack\User::all()->last();
         $password = $user->password;
@@ -136,7 +158,7 @@ class AuthTest extends TestCase
             ->notSeeInDatabase('users', ['name' => $user->name]);
     }
 
-    public function testUserPasswordUpdate()
+    public function test_user_password_update()
     {
         $user = \BookStack\User::all()->last();
         $userProfilePage = '/users/' . $user->id;
@@ -156,7 +178,7 @@ class AuthTest extends TestCase
             $this->assertTrue(Hash::check('newpassword', $userPassword));
     }
 
-    public function testUserDeletion()
+    public function test_user_deletion()
     {
         $userDetails = factory(\BookStack\User::class)->make();
         $user = $this->getNewUser($userDetails->toArray());
@@ -170,7 +192,7 @@ class AuthTest extends TestCase
             ->notSeeInDatabase('users', ['name' => $user->name]);
     }
 
-    public function testUserCannotBeDeletedIfLastAdmin()
+    public function test_user_cannot_be_deleted_if_last_admin()
     {
         $adminRole = \BookStack\Role::getRole('admin');
         // Ensure we currently only have 1 admin user
@@ -184,7 +206,7 @@ class AuthTest extends TestCase
             ->see('You cannot delete the only admin');
     }
 
-    public function testLogout()
+    public function test_logout()
     {
         $this->asAdmin()
             ->visit('/')
@@ -200,7 +222,7 @@ class AuthTest extends TestCase
      * @param string $password
      * @return $this
      */
-    private function login($email, $password)
+    protected function login($email, $password)
     {
         return $this->visit('/login')
             ->type($email, '#email')
diff --git a/tests/Auth/LdapTest.php b/tests/Auth/LdapTest.php
new file mode 100644 (file)
index 0000000..6b026da
--- /dev/null
@@ -0,0 +1,43 @@
+<?php
+
+use BookStack\Services\LdapService;
+use BookStack\User;
+
+class LdapTest extends \TestCase
+{
+
+    protected $mockLdap;
+    protected $mockUser;
+    protected $resourceId = 'resource-test';
+
+    public function setUp()
+    {
+        parent::setUp();
+        app('config')->set(['auth.method' => 'ldap', 'services.ldap.base_dn' => 'dc=ldap,dc=local', 'auth.providers.users.driver' => 'ldap']);
+        $this->mockLdap = Mockery::mock(BookStack\Services\Ldap::class);
+        $this->app['BookStack\Services\Ldap'] = $this->mockLdap;
+        $this->mockUser = factory(User::class)->make();
+    }
+
+    public function test_ldap_login()
+    {
+        $this->mockLdap->shouldReceive('connect')->once()->andReturn($this->resourceId);
+        $this->mockLdap->shouldReceive('setOption')->once();
+        $this->mockLdap->shouldReceive('searchAndGetEntries')->twice()
+            ->with($this->resourceId, config('services.ldap.base_dn'), Mockery::type('string'), Mockery::type('array'))
+            ->andReturn(['count' => 1, 0 => [
+                'uid' => [$this->mockUser->name],
+                'cn' => [$this->mockUser->name],
+                'dn'    => ['dc=test'.config('services.ldap.base_dn')]
+            ]]);
+        $this->mockLdap->shouldReceive('bind')->times(1)->andReturn(true);
+
+        $this->visit('/login')
+            ->see('Username')
+            ->type($this->mockUser->name, '#username')
+            ->type($this->mockUser->password, '#password')
+            ->press('Sign In')
+            ->seePageIs('/login')->see('Please enter an email to use for this account.');
+    }
+
+}
\ No newline at end of file
similarity index 82%
rename from tests/SocialAuthTest.php
rename to tests/Auth/SocialAuthTest.php
index 820ecd4dd5fd3cea4de56a7474c162112b96cba3..d5a7e692115c568121e688d548cbe5dc75e8d21f 100644 (file)
@@ -3,13 +3,13 @@
 class SocialAuthTest extends TestCase
 {
 
-    public function testSocialRegistration()
+    public function test_social_registration()
     {
         // http://docs.mockery.io/en/latest/reference/startup_methods.html
         $user = factory(\BookStack\User::class)->make();
 
         $this->setSettings(['registration-enabled' => 'true']);
-        $this->setEnvironment(['GOOGLE_APP_ID' => 'abc123', 'GOOGLE_APP_SECRET' => '123abc', 'APP_URL' => 'http://localhost']);
+        config(['GOOGLE_APP_ID' => 'abc123', 'GOOGLE_APP_SECRET' => '123abc', 'APP_URL' => 'http://localhost']);
 
         $mockSocialite = Mockery::mock('Laravel\Socialite\Contracts\Factory');
         $this->app['Laravel\Socialite\Contracts\Factory'] = $mockSocialite;
@@ -32,11 +32,4 @@ class SocialAuthTest extends TestCase
         $this->seeInDatabase('social_accounts', ['user_id' => $user->id]);
     }
 
-    protected function setEnvironment($array)
-    {
-        foreach ($array as $key => $value) {
-            putenv("$key=$value");
-        }
-    }
-
 }
index 1eda7c73c2775e52dff5d0781e676dc3c373abc4..5bfedb53561952cde7d362e1d03e044e70cb926c 100644 (file)
@@ -5,7 +5,7 @@ use Illuminate\Support\Facades\DB;
 class EntityTest extends TestCase
 {
 
-    public function testEntityCreation()
+    public function test_entity_creation()
     {
 
         // Test Creation
@@ -51,7 +51,7 @@ class EntityTest extends TestCase
         return \BookStack\Book::find($book->id);
     }
 
-    public function testBookSortPageShows()
+    public function test_book_sort_page_shows()
     {
         $books =  \BookStack\Book::all();
         $bookToSort = $books[0];
@@ -65,7 +65,7 @@ class EntityTest extends TestCase
             ->see($books[1]->name);
     }
 
-    public function testBookSortItemReturnsBookContent()
+    public function test_book_sort_item_returns_book_content()
     {
         $books =  \BookStack\Book::all();
         $bookToSort = $books[0];
@@ -155,7 +155,7 @@ class EntityTest extends TestCase
         return $book;
     }
 
-    public function testPageSearch()
+    public function test_page_search()
     {
         $book = \BookStack\Book::all()->first();
         $page = $book->pages->first();
@@ -170,7 +170,7 @@ class EntityTest extends TestCase
             ->seePageIs($page->getUrl());
     }
 
-    public function testInvalidPageSearch()
+    public function test_invalid_page_search()
     {
         $this->asAdmin()
             ->visit('/')
@@ -180,7 +180,7 @@ class EntityTest extends TestCase
             ->seeStatusCode(200);
     }
 
-    public function testEmptySearchRedirectsBack()
+    public function test_empty_search_redirects_back()
     {
         $this->asAdmin()
             ->visit('/')
@@ -188,7 +188,7 @@ class EntityTest extends TestCase
             ->seePageIs('/');
     }
 
-    public function testBookSearch()
+    public function test_book_search()
     {
         $book = \BookStack\Book::all()->first();
         $page = $book->pages->last();
@@ -202,7 +202,7 @@ class EntityTest extends TestCase
             ->see($chapter->name);
     }
 
-    public function testEmptyBookSearchRedirectsBack()
+    public function test_empty_book_search_redirects_back()
     {
         $book = \BookStack\Book::all()->first();
         $this->asAdmin()
@@ -212,7 +212,7 @@ class EntityTest extends TestCase
     }
 
 
-    public function testEntitiesViewableAfterCreatorDeletion()
+    public function test_entities_viewable_after_creator_deletion()
     {
         // Create required assets and revisions
         $creator = $this->getNewUser();
@@ -225,7 +225,7 @@ class EntityTest extends TestCase
         $this->checkEntitiesViewable($entities);
     }
 
-    public function testEntitiesViewableAfterUpdaterDeletion()
+    public function test_entities_viewable_after_updater_deletion()
     {
         // Create required assets and revisions
         $creator = $this->getNewUser();
index b5141f0f6e5126b700fcbdd1bae26910caaddc77..58e39dfd9ae8b504a1d5dfe6e3d4527d28d4e0db 100644 (file)
@@ -3,7 +3,7 @@
 class PublicViewTest extends TestCase
 {
 
-    public function testBooksViewable()
+    public function test_books_viewable()
     {
         $this->setSettings(['app-public' => 'true']);
         $books = \BookStack\Book::orderBy('name', 'asc')->take(10)->get();
@@ -13,14 +13,14 @@ class PublicViewTest extends TestCase
         $this->visit('/books')
             ->seeStatusCode(200)
             ->see($books[0]->name)
-            // Check indavidual book page is showing and it's child contents are visible.
+            // Check individual book page is showing and it's child contents are visible.
             ->click($bookToVisit->name)
             ->seePageIs($bookToVisit->getUrl())
             ->see($bookToVisit->name)
             ->see($bookToVisit->chapters()->first()->name);
     }
 
-    public function testChaptersViewable()
+    public function test_chapters_viewable()
     {
         $this->setSettings(['app-public' => 'true']);
         $chapterToVisit = \BookStack\Chapter::first();
@@ -30,7 +30,7 @@ class PublicViewTest extends TestCase
         $this->visit($chapterToVisit->getUrl())
             ->seeStatusCode(200)
             ->see($chapterToVisit->name)
-            // Check indavidual chapter page is showing and it's child contents are visible.
+            // Check individual chapter page is showing and it's child contents are visible.
             ->see($pageToVisit->name)
             ->click($pageToVisit->name)
             ->see($chapterToVisit->book->name)