2018-04-14 13:47:13 -04:00
< ? php namespace Tests ;
2019-10-05 07:55:01 -04:00
use BookStack\Auth\User ;
2020-11-21 19:17:45 -05:00
use BookStack\Entities\Models\Book ;
use BookStack\Entities\Models\Bookshelf ;
use BookStack\Entities\Models\Chapter ;
use BookStack\Entities\Models\Entity ;
use BookStack\Entities\Models\Page ;
2019-10-05 07:55:01 -04:00
use BookStack\Entities\Repos\BookRepo ;
use BookStack\Entities\Repos\BookshelfRepo ;
use BookStack\Entities\Repos\ChapterRepo ;
2018-09-25 07:30:50 -04:00
use BookStack\Auth\Permissions\PermissionsRepo ;
use BookStack\Auth\Role ;
use BookStack\Auth\Permissions\PermissionService ;
2018-10-13 06:27:55 -04:00
use BookStack\Entities\Repos\PageRepo ;
2018-09-25 07:30:50 -04:00
use BookStack\Settings\SettingService ;
2019-07-17 17:36:49 -04:00
use BookStack\Uploads\HttpFetcher ;
2020-11-06 07:54:39 -05:00
use Illuminate\Http\Response ;
2019-09-14 09:12:39 -04:00
use Illuminate\Support\Env ;
2020-05-23 06:26:48 -04:00
use Illuminate\Support\Facades\Log ;
2019-10-05 07:55:01 -04:00
use Mockery ;
2020-05-23 06:26:48 -04:00
use Monolog\Handler\TestHandler ;
use Monolog\Logger ;
2019-10-05 07:55:01 -04:00
use Throwable ;
2020-11-06 07:54:39 -05:00
use Illuminate\Foundation\Testing\Assert as PHPUnit ;
2018-04-14 13:47:13 -04:00
trait SharedTestHelpers
{
protected $admin ;
protected $editor ;
/**
* Set the current user context to be an admin .
* @ return $this
*/
public function asAdmin ()
{
return $this -> actingAs ( $this -> getAdmin ());
}
/**
* Get the current admin user .
* @ return mixed
*/
public function getAdmin () {
if ( $this -> admin === null ) {
$adminRole = Role :: getSystemRole ( 'admin' );
$this -> admin = $adminRole -> users -> first ();
}
return $this -> admin ;
}
/**
* Set the current user context to be an editor .
* @ return $this
*/
public function asEditor ()
{
return $this -> actingAs ( $this -> getEditor ());
}
/**
* Get a editor user .
* @ return mixed
*/
protected function getEditor () {
if ( $this -> editor === null ) {
$editorRole = Role :: getRole ( 'editor' );
$this -> editor = $editorRole -> users -> first ();
}
return $this -> editor ;
}
/**
2020-05-23 06:26:48 -04:00
* Get an instance of a user with 'viewer' permissions .
2018-04-14 13:47:13 -04:00
*/
2020-05-23 06:26:48 -04:00
protected function getViewer ( array $attributes = []) : User
2018-04-14 13:47:13 -04:00
{
2019-10-05 07:55:01 -04:00
$user = Role :: getRole ( 'viewer' ) -> users () -> first ();
2020-05-23 06:26:48 -04:00
if ( ! empty ( $attributes )) {
$user -> forceFill ( $attributes ) -> save ();
}
2018-04-14 13:47:13 -04:00
return $user ;
}
2018-09-21 10:15:16 -04:00
/**
* Regenerate the permission for an entity .
* @ param Entity $entity
2019-10-05 07:55:01 -04:00
* @ throws Throwable
2018-09-21 10:15:16 -04:00
*/
protected function regenEntityPermissions ( Entity $entity )
{
2019-09-19 19:18:28 -04:00
$entity -> rebuildPermissions ();
2018-09-21 10:15:16 -04:00
$entity -> load ( 'jointPermissions' );
}
/**
* Create and return a new bookshelf .
* @ param array $input
2019-10-05 07:55:01 -04:00
* @ return Bookshelf
2018-09-21 10:15:16 -04:00
*/
public function newShelf ( $input = [ 'name' => 'test shelf' , 'description' => 'My new test shelf' ]) {
2019-10-05 07:55:01 -04:00
return app ( BookshelfRepo :: class ) -> create ( $input , []);
2018-09-21 10:15:16 -04:00
}
2018-04-14 13:47:13 -04:00
/**
* Create and return a new book .
* @ param array $input
* @ return Book
*/
public function newBook ( $input = [ 'name' => 'test book' , 'description' => 'My new test book' ]) {
2019-10-05 07:55:01 -04:00
return app ( BookRepo :: class ) -> create ( $input );
2018-04-14 13:47:13 -04:00
}
/**
* Create and return a new test chapter
* @ param array $input
* @ param Book $book
2019-10-05 07:55:01 -04:00
* @ return Chapter
2018-04-14 13:47:13 -04:00
*/
public function newChapter ( $input = [ 'name' => 'test chapter' , 'description' => 'My new test chapter' ], Book $book ) {
2019-10-05 07:55:01 -04:00
return app ( ChapterRepo :: class ) -> create ( $input , $book );
2018-04-14 13:47:13 -04:00
}
/**
* Create and return a new test page
* @ param array $input
2018-09-23 10:15:44 -04:00
* @ return Page
2019-10-05 07:55:01 -04:00
* @ throws Throwable
2018-04-14 13:47:13 -04:00
*/
public function newPage ( $input = [ 'name' => 'test page' , 'html' => 'My new test page' ]) {
$book = Book :: first ();
2018-10-13 06:27:55 -04:00
$pageRepo = app ( PageRepo :: class );
2019-10-05 07:55:01 -04:00
$draftPage = $pageRepo -> getNewDraftPage ( $book );
return $pageRepo -> publishDraft ( $draftPage , $input );
2018-04-14 13:47:13 -04:00
}
/**
* Quickly sets an array of settings .
* @ param $settingsArray
*/
protected function setSettings ( $settingsArray )
{
$settings = app ( SettingService :: class );
foreach ( $settingsArray as $key => $value ) {
$settings -> put ( $key , $value );
}
}
/**
* Manually set some permissions on an entity .
* @ param Entity $entity
* @ param array $actions
* @ param array $roles
*/
protected function setEntityRestrictions ( Entity $entity , $actions = [], $roles = [])
{
$entity -> restricted = true ;
$entity -> permissions () -> delete ();
$permissions = [];
foreach ( $actions as $action ) {
foreach ( $roles as $role ) {
$permissions [] = [
'role_id' => $role -> id ,
'action' => strtolower ( $action )
];
}
}
$entity -> permissions () -> createMany ( $permissions );
$entity -> save ();
$entity -> load ( 'permissions' );
$this -> app [ PermissionService :: class ] -> buildJointPermissionsForEntity ( $entity );
$entity -> load ( 'jointPermissions' );
}
2018-09-21 10:15:16 -04:00
/**
* Give the given user some permissions .
*/
2021-01-01 20:22:41 -05:00
protected function giveUserPermissions ( User $user , array $permissions = [])
2018-09-21 10:15:16 -04:00
{
$newRole = $this -> createNewRole ( $permissions );
$user -> attachRole ( $newRole );
$user -> load ( 'roles' );
2021-01-01 20:22:41 -05:00
$user -> clearPermissionCache ();
2018-09-21 10:15:16 -04:00
}
/**
* Create a new basic role for testing purposes .
* @ param array $permissions
* @ return Role
*/
protected function createNewRole ( $permissions = [])
{
$permissionRepo = app ( PermissionsRepo :: class );
$roleData = factory ( Role :: class ) -> make () -> toArray ();
$roleData [ 'permissions' ] = array_flip ( $permissions );
return $permissionRepo -> saveNewRole ( $roleData );
}
2019-07-17 17:36:49 -04:00
/**
* Mock the HttpFetcher service and return the given data on fetch .
* @ param $returnData
* @ param int $times
*/
protected function mockHttpFetch ( $returnData , int $times = 1 )
{
2019-10-05 07:55:01 -04:00
$mockHttp = Mockery :: mock ( HttpFetcher :: class );
2019-07-17 17:36:49 -04:00
$this -> app [ HttpFetcher :: class ] = $mockHttp ;
$mockHttp -> shouldReceive ( 'fetch' )
-> times ( $times )
-> andReturn ( $returnData );
}
2019-09-14 09:12:39 -04:00
/**
* Run a set test with the given env variable .
* Remembers the original and resets the value after test .
* @ param string $name
* @ param $value
* @ param callable $callback
*/
protected function runWithEnv ( string $name , $value , callable $callback )
{
Env :: disablePutenv ();
2019-09-19 20:18:59 -04:00
$originalVal = $_SERVER [ $name ] ? ? null ;
2019-09-14 09:12:39 -04:00
if ( is_null ( $value )) {
unset ( $_SERVER [ $name ]);
} else {
$_SERVER [ $name ] = $value ;
}
$this -> refreshApplication ();
$callback ();
if ( is_null ( $originalVal )) {
unset ( $_SERVER [ $name ]);
} else {
$_SERVER [ $name ] = $originalVal ;
}
}
/**
* Check the keys and properties in the given map to include
* exist , albeit not exclusively , within the map to check .
* @ param array $mapToInclude
* @ param array $mapToCheck
* @ param string $message
*/
protected function assertArrayMapIncludes ( array $mapToInclude , array $mapToCheck , string $message = '' ) : void
{
$passed = true ;
foreach ( $mapToInclude as $key => $value ) {
if ( ! isset ( $mapToCheck [ $key ]) || $mapToCheck [ $key ] !== $mapToInclude [ $key ]) {
$passed = false ;
}
}
$toIncludeStr = print_r ( $mapToInclude , true );
$toCheckStr = print_r ( $mapToCheck , true );
self :: assertThat ( $passed , self :: isTrue (), " Failed asserting that given map: \n \n { $toCheckStr } \n \n includes: \n \n { $toIncludeStr } " );
}
2020-02-02 08:10:21 -05:00
/**
* Assert a permission error has occurred .
*/
protected function assertPermissionError ( $response )
{
2020-11-06 07:54:39 -05:00
PHPUnit :: assertTrue ( $this -> isPermissionError ( $response -> baseResponse ? ? $response -> response ), " Failed asserting the response contains a permission error. " );
}
2020-02-02 08:10:21 -05:00
2020-11-06 07:54:39 -05:00
/**
* Assert a permission error has occurred .
*/
protected function assertNotPermissionError ( $response )
{
PHPUnit :: assertFalse ( $this -> isPermissionError ( $response -> baseResponse ? ? $response -> response ), " Failed asserting the response does not contain a permission error. " );
}
/**
* Check if the given response is a permission error .
*/
private function isPermissionError ( $response ) : bool
{
return $response -> status () === 302
&& $response -> headers -> get ( 'Location' ) === url ( '/' )
&& strpos ( session () -> pull ( 'error' , '' ), 'You do not have permission to access' ) === 0 ;
2020-02-02 08:10:21 -05:00
}
2020-05-23 06:26:48 -04:00
/**
* Set a test handler as the logging interface for the application .
* Allows capture of logs for checking against during tests .
*/
protected function withTestLogger () : TestHandler
{
$monolog = new Logger ( 'testing' );
$testHandler = new TestHandler ();
$monolog -> pushHandler ( $testHandler );
Log :: extend ( 'testing' , function () use ( $monolog ) {
return $monolog ;
});
Log :: setDefaultDriver ( 'testing' );
return $testHandler ;
}
2018-04-14 13:47:13 -04:00
}