2023-09-18 19:07:30 +02:00
< ? php
namespace Tests\Commands ;
2023-09-19 16:53:01 +02:00
use BookStack\Uploads\Image ;
2023-09-18 19:07:30 +02:00
use BookStack\Users\Models\User ;
use GuzzleHttp\Psr7\Response ;
use Illuminate\Database\Eloquent\Collection ;
use Tests\TestCase ;
2023-09-19 16:53:01 +02:00
class RefreshAvatarCommandTest extends TestCase
2023-09-18 19:07:30 +02:00
{
2023-09-19 16:53:01 +02:00
public function setUp () : void
{
parent :: setUp ();
config () -> set ([
'services.disable_services' => false ,
'services.avatar_url' => 'https://avatars.example.com?a=b' ,
]);
}
public function test_command_errors_if_avatar_fetch_disabled ()
{
config () -> set ([ 'services.avatar_url' => false ]);
$this -> artisan ( 'bookstack:refresh-avatar' )
-> expectsOutputToContain ( " Avatar fetching is disabled on this instance " )
-> assertExitCode ( 1 );
}
2023-09-18 19:07:30 +02:00
public function test_command_requires_email_or_id_option ()
{
2023-09-19 16:53:01 +02:00
$this -> artisan ( 'bookstack:refresh-avatar' )
-> expectsOutputToContain ( " Either a --id=<number> or --email=<email> option must be provided " )
-> assertExitCode ( 1 );
2023-09-18 19:07:30 +02:00
}
public function test_command_runs_with_provided_email ()
{
$requests = $this -> mockHttpClient ([ new Response ( 200 , [ 'Content-Type' => 'image/png' ], $this -> files -> pngImageData ())]);
2023-09-19 16:53:01 +02:00
$user = $this -> users -> viewer ();
2023-09-18 19:07:30 +02:00
$this -> assertFalse ( $user -> avatar () -> exists ());
2023-09-19 16:53:01 +02:00
$this -> artisan ( " bookstack:refresh-avatar --email= { $user -> email } -f " )
2023-09-18 19:07:30 +02:00
-> expectsQuestion ( 'Are you sure you want to proceed?' , true )
2023-09-19 16:53:01 +02:00
-> expectsOutput ( " [ID: { $user -> id } ] { $user -> email } - Updated " )
-> expectsOutputToContain ( 'This will destroy any existing avatar images these users have, and attempt to fetch new avatar images from avatars.example.com' )
-> assertExitCode ( 0 );
2023-09-18 19:07:30 +02:00
2023-09-19 16:53:01 +02:00
$this -> assertEquals ( 'https://avatars.example.com?a=b' , $requests -> latestRequest () -> getUri ());
2023-09-18 19:07:30 +02:00
$user -> refresh ();
$this -> assertTrue ( $user -> avatar () -> exists ());
}
public function test_command_runs_with_provided_id ()
{
$requests = $this -> mockHttpClient ([ new Response ( 200 , [ 'Content-Type' => 'image/png' ], $this -> files -> pngImageData ())]);
2023-09-19 16:53:01 +02:00
$user = $this -> users -> viewer ();
2023-09-18 19:07:30 +02:00
$this -> assertFalse ( $user -> avatar () -> exists ());
2023-09-19 16:53:01 +02:00
$this -> artisan ( " bookstack:refresh-avatar --id= { $user -> id } -f " )
2023-09-18 19:07:30 +02:00
-> expectsQuestion ( 'Are you sure you want to proceed?' , true )
2023-09-19 16:53:01 +02:00
-> expectsOutput ( " [ID: { $user -> id } ] { $user -> email } - Updated " )
-> assertExitCode ( 0 );
2023-09-18 19:07:30 +02:00
2023-09-19 16:53:01 +02:00
$this -> assertEquals ( 'https://avatars.example.com?a=b' , $requests -> latestRequest () -> getUri ());
2023-09-18 19:07:30 +02:00
$user -> refresh ();
$this -> assertTrue ( $user -> avatar () -> exists ());
}
public function test_command_runs_with_provided_id_error_upstream ()
{
$requests = $this -> mockHttpClient ([ new Response ( 404 )]);
2023-09-19 16:53:01 +02:00
$user = $this -> users -> viewer ();
$this -> assertFalse ( $user -> avatar () -> exists ());
2023-09-18 19:07:30 +02:00
2023-09-19 16:53:01 +02:00
$this -> artisan ( " bookstack:refresh-avatar --id= { $user -> id } -f " )
2023-09-18 19:07:30 +02:00
-> expectsQuestion ( 'Are you sure you want to proceed?' , true )
2023-09-19 16:53:01 +02:00
-> expectsOutput ( " [ID: { $user -> id } ] { $user -> email } - Not updated " )
-> assertExitCode ( 1 );
2023-09-18 19:07:30 +02:00
$this -> assertEquals ( 1 , $requests -> requestCount ());
2023-09-19 16:53:01 +02:00
$this -> assertFalse ( $user -> avatar () -> exists ());
2023-09-18 19:07:30 +02:00
}
public function test_saying_no_to_confirmation_does_not_refresh_avatar ()
{
2023-09-19 16:53:01 +02:00
$user = $this -> users -> viewer ();
2023-09-18 19:07:30 +02:00
$this -> assertFalse ( $user -> avatar () -> exists ());
2023-09-19 16:53:01 +02:00
$this -> artisan ( " bookstack:refresh-avatar --id= { $user -> id } -f " )
2023-09-18 19:07:30 +02:00
-> expectsQuestion ( 'Are you sure you want to proceed?' , false )
2023-09-19 16:53:01 +02:00
-> assertExitCode ( 0 );
2023-09-18 19:07:30 +02:00
$this -> assertFalse ( $user -> avatar () -> exists ());
}
public function test_giving_non_existing_user_shows_error_message ()
{
2023-09-19 16:53:01 +02:00
$this -> artisan ( 'bookstack:refresh-avatar --email=donkeys@example.com' )
2023-09-18 19:07:30 +02:00
-> expectsOutput ( 'A user where email=donkeys@example.com could not be found.' )
2023-09-19 16:53:01 +02:00
-> assertExitCode ( 1 );
2023-09-18 19:07:30 +02:00
}
public function test_command_runs_all_users_without_avatars_dry_run ()
{
$users = User :: query () -> where ( 'image_id' , '=' , 0 ) -> get ();
2023-09-19 16:53:01 +02:00
$this -> artisan ( 'bookstack:refresh-avatar --users-without-avatars' )
-> expectsOutput ( count ( $users ) . ' user(s) found to update avatars for.' )
-> expectsOutput ( " [ID: { $users [ 0 ] -> id } ] { $users [ 0 ] -> email } - Not updated " )
-> expectsOutput ( 'Dry run, no avatars were updated.' )
-> assertExitCode ( 0 );
2023-09-18 19:07:30 +02:00
}
2023-09-19 16:53:01 +02:00
public function test_command_runs_all_users_without_avatars_with_none_to_update ()
2023-09-18 19:07:30 +02:00
{
2023-09-19 16:53:01 +02:00
$requests = $this -> mockHttpClient ();
$image = Image :: factory () -> create ();
User :: query () -> update ([ 'image_id' => $image -> id ]);
2023-09-18 19:07:30 +02:00
2023-09-19 16:53:01 +02:00
$this -> artisan ( 'bookstack:refresh-avatar --users-without-avatars -f' )
-> expectsOutput ( '0 user(s) found to update avatars for.' )
-> assertExitCode ( 0 );
2023-09-18 19:07:30 +02:00
$this -> assertEquals ( 0 , $requests -> requestCount ());
}
public function test_command_runs_all_users_without_avatars ()
{
/** @var Collection|User[] $users */
$users = User :: query () -> where ( 'image_id' , '=' , 0 ) -> get ();
2023-09-19 16:53:01 +02:00
$pendingCommand = $this -> artisan ( 'bookstack:refresh-avatar --users-without-avatars -f' );
2023-09-18 19:07:30 +02:00
$pendingCommand
2023-09-19 16:53:01 +02:00
-> expectsOutput ( $users -> count () . ' user(s) found to update avatars for.' )
-> expectsQuestion ( 'Are you sure you want to proceed?' , true );
2023-09-18 19:07:30 +02:00
$responses = [];
foreach ( $users as $user ) {
2023-09-19 16:53:01 +02:00
$pendingCommand -> expectsOutput ( " [ID: { $user -> id } ] { $user -> email } - Updated " );
2023-09-18 19:07:30 +02:00
$responses [] = new Response ( 200 , [ 'Content-Type' => 'image/png' ], $this -> files -> pngImageData ());
}
$requests = $this -> mockHttpClient ( $responses );
2023-09-19 16:53:01 +02:00
$pendingCommand -> assertExitCode ( 0 );
2023-09-18 19:07:30 +02:00
$pendingCommand -> run ();
2023-09-19 16:53:01 +02:00
$this -> assertEquals ( 0 , User :: query () -> where ( 'image_id' , '=' , 0 ) -> count ());
2023-09-18 19:07:30 +02:00
$this -> assertEquals ( $users -> count (), $requests -> requestCount ());
}
public function test_saying_no_to_confirmation_all_users_without_avatars ()
{
2023-09-19 16:53:01 +02:00
$requests = $this -> mockHttpClient ();
2023-09-18 19:07:30 +02:00
2023-09-19 16:53:01 +02:00
$this -> artisan ( 'bookstack:refresh-avatar --users-without-avatars -f' )
-> expectsQuestion ( 'Are you sure you want to proceed?' , false )
-> assertExitCode ( 0 );
2023-09-18 19:07:30 +02:00
$this -> assertEquals ( 0 , $requests -> requestCount ());
}
public function test_command_runs_all_users_dry_run ()
{
$users = User :: query () -> where ( 'image_id' , '=' , 0 ) -> get ();
2023-09-19 16:53:01 +02:00
$this -> artisan ( 'bookstack:refresh-avatar --all' )
-> expectsOutput ( count ( $users ) . ' user(s) found to update avatars for.' )
-> expectsOutput ( " [ID: { $users [ 0 ] -> id } ] { $users [ 0 ] -> email } - Not updated " )
-> expectsOutput ( 'Dry run, no avatars were updated.' )
-> assertExitCode ( 0 );
2023-09-18 19:07:30 +02:00
}
public function test_command_runs_update_all_users_avatar ()
{
/** @var Collection|User[] $users */
$users = User :: query () -> get ();
2023-09-19 16:53:01 +02:00
$pendingCommand = $this -> artisan ( 'bookstack:refresh-avatar --all -f' );
2023-09-18 19:07:30 +02:00
$pendingCommand
2023-09-19 16:53:01 +02:00
-> expectsOutput ( $users -> count () . ' user(s) found to update avatars for.' )
-> expectsQuestion ( 'Are you sure you want to proceed?' , true );
2023-09-18 19:07:30 +02:00
$responses = [];
foreach ( $users as $user ) {
2023-09-19 16:53:01 +02:00
$pendingCommand -> expectsOutput ( " [ID: { $user -> id } ] { $user -> email } - Updated " );
2023-09-18 19:07:30 +02:00
$responses [] = new Response ( 200 , [ 'Content-Type' => 'image/png' ], $this -> files -> pngImageData ());
}
$requests = $this -> mockHttpClient ( $responses );
2023-09-19 16:53:01 +02:00
$pendingCommand -> assertExitCode ( 0 );
2023-09-18 19:07:30 +02:00
$pendingCommand -> run ();
2023-09-19 16:53:01 +02:00
$this -> assertEquals ( 0 , User :: query () -> where ( 'image_id' , '=' , 0 ) -> count ());
2023-09-18 19:07:30 +02:00
$this -> assertEquals ( $users -> count (), $requests -> requestCount ());
}
public function test_command_runs_update_all_users_avatar_errors ()
{
/** @var Collection|User[] $users */
2023-09-19 16:53:01 +02:00
$users = array_values ( User :: query () -> get () -> all ());
2023-09-18 19:07:30 +02:00
2023-09-19 16:53:01 +02:00
$pendingCommand = $this -> artisan ( 'bookstack:refresh-avatar --all -f' );
2023-09-18 19:07:30 +02:00
$pendingCommand
2023-09-19 16:53:01 +02:00
-> expectsOutput ( count ( $users ) . ' user(s) found to update avatars for.' )
-> expectsQuestion ( 'Are you sure you want to proceed?' , true );
2023-09-18 19:07:30 +02:00
$responses = [];
2023-09-19 16:53:01 +02:00
foreach ( $users as $index => $user ) {
if ( $index === 0 ) {
$pendingCommand -> expectsOutput ( " [ID: { $user -> id } ] { $user -> email } - Not updated " );
2023-09-18 19:07:30 +02:00
$responses [] = new Response ( 404 );
continue ;
}
2023-09-19 16:53:01 +02:00
$pendingCommand -> expectsOutput ( " [ID: { $user -> id } ] { $user -> email } - Updated " );
2023-09-18 19:07:30 +02:00
$responses [] = new Response ( 200 , [ 'Content-Type' => 'image/png' ], $this -> files -> pngImageData ());
}
$requests = $this -> mockHttpClient ( $responses );
2023-09-19 16:53:01 +02:00
$pendingCommand -> assertExitCode ( 1 );
2023-09-18 19:07:30 +02:00
$pendingCommand -> run ();
$userWithAvatars = User :: query () -> where ( 'image_id' , '!=' , 0 ) -> count ();
2023-09-19 16:53:01 +02:00
$this -> assertEquals ( count ( $users ) - 1 , $userWithAvatars );
$this -> assertEquals ( count ( $users ), $requests -> requestCount ());
2023-09-18 19:07:30 +02:00
}
public function test_saying_no_to_confirmation_update_all_users_avatar ()
{
$requests = $this -> mockHttpClient ([ new Response ( 200 , [ 'Content-Type' => 'image/png' ], $this -> files -> pngImageData ())]);
2023-09-19 16:53:01 +02:00
$this -> artisan ( 'bookstack:refresh-avatar --all -f' )
-> expectsQuestion ( 'Are you sure you want to proceed?' , false )
-> assertExitCode ( 0 );
2023-09-18 19:07:30 +02:00
$this -> assertEquals ( 0 , $requests -> requestCount ());
}
}