]> BookStack Code Mirror - bookstack/blobdiff - tests/Commands/RefreshAvatarCommandTest.php
respective book and chapter structure added.
[bookstack] / tests / Commands / RefreshAvatarCommandTest.php
index d625097efedb8094b9f76d9c50d135eec9465b52..6126f21a8a7912e55b3a1922cde8e43a76a37ca1 100644 (file)
@@ -1,47 +1,55 @@
 <?php
 
-declare(strict_types=1);
-
 namespace Tests\Commands;
 
-use BookStack\Console\Commands\RefreshAvatarCommand;
-use BookStack\Uploads\UserAvatars;
+use BookStack\Uploads\Image;
 use BookStack\Users\Models\User;
 use GuzzleHttp\Psr7\Response;
 use Illuminate\Database\Eloquent\Collection;
-use Symfony\Component\Console\Command\Command;
 use Tests\TestCase;
 
-final class RefreshAvatarCommandTest extends TestCase
+class RefreshAvatarCommandTest extends TestCase
 {
+    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);
+    }
+
     public function test_command_requires_email_or_id_option()
     {
-        $this->artisan(RefreshAvatarCommand::class)
-            ->expectsOutput('Either a --id=<number> or --email=<email> option must be provided.')
-            ->assertExitCode(Command::FAILURE);
+        $this->artisan('bookstack:refresh-avatar')
+            ->expectsOutputToContain("Either a --id=<number> or --email=<email> option must be provided")
+            ->assertExitCode(1);
     }
 
     public function test_command_runs_with_provided_email()
     {
         $requests = $this->mockHttpClient([new Response(200, ['Content-Type' => 'image/png'], $this->files->pngImageData())]);
-        config()->set(['services.disable_services' => false]);
-
-        /** @var User $user */
-        $user = User::query()->first();
-
-        /** @var UserAvatars $avatar */
-        $avatar = app()->make(UserAvatars::class);
-        $avatar->destroyAllForUser($user);
 
+        $user = $this->users->viewer();
         $this->assertFalse($user->avatar()->exists());
-        $this->artisan(RefreshAvatarCommand::class, ['--email' => $user->email])
-            ->expectsOutputToContain("- ID: {$user->id}")
+
+        $this->artisan("bookstack:refresh-avatar --email={$user->email} -f")
             ->expectsQuestion('Are you sure you want to proceed?', true)
-            ->expectsOutput('User avatar has been updated.')
-            ->assertExitCode(Command::SUCCESS);
+            ->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);
 
-        $expectedUri = 'https://www.gravatar.com/avatar/' . md5(strtolower($user->email)) . '?s=500&d=identicon';
-        $this->assertEquals($expectedUri, $requests->latestRequest()->getUri());
+        $this->assertEquals('https://avatars.example.com?a=b', $requests->latestRequest()->getUri());
 
         $user->refresh();
         $this->assertTrue($user->avatar()->exists());
@@ -50,24 +58,16 @@ final class RefreshAvatarCommandTest extends TestCase
     public function test_command_runs_with_provided_id()
     {
         $requests = $this->mockHttpClient([new Response(200, ['Content-Type' => 'image/png'], $this->files->pngImageData())]);
-        config()->set(['services.disable_services' => false]);
-
-        /** @var User $user */
-        $user = User::query()->first();
-
-        /** @var UserAvatars $avatar */
-        $avatar = app()->make(UserAvatars::class);
-        $avatar->destroyAllForUser($user);
 
+        $user = $this->users->viewer();
         $this->assertFalse($user->avatar()->exists());
-        $this->artisan(RefreshAvatarCommand::class, ['--id' => $user->id])
-            ->expectsOutputToContain("- ID: {$user->id}")
+
+        $this->artisan("bookstack:refresh-avatar --id={$user->id} -f")
             ->expectsQuestion('Are you sure you want to proceed?', true)
-            ->expectsOutput('User avatar has been updated.')
-            ->assertExitCode(Command::SUCCESS);
+            ->expectsOutput("[ID: {$user->id}] {$user->email} - Updated")
+            ->assertExitCode(0);
 
-        $expectedUri = 'https://www.gravatar.com/avatar/' . md5(strtolower($user->email)) . '?s=500&d=identicon';
-        $this->assertEquals($expectedUri, $requests->latestRequest()->getUri());
+        $this->assertEquals('https://avatars.example.com?a=b', $requests->latestRequest()->getUri());
 
         $user->refresh();
         $this->assertTrue($user->avatar()->exists());
@@ -76,143 +76,93 @@ final class RefreshAvatarCommandTest extends TestCase
     public function test_command_runs_with_provided_id_error_upstream()
     {
         $requests = $this->mockHttpClient([new Response(404)]);
-        config()->set(['services.disable_services' => false]);
 
-        /** @var User $user */
-        $user = User::query()->first();
-        /** @var UserAvatars $avatar */
-        $avatar = app()->make(UserAvatars::class);
-        $avatar->assignToUserFromExistingData($user, $this->files->pngImageData(), 'png');
-
-        $oldId = $user->avatar->id ?? 0;
+        $user = $this->users->viewer();
+        $this->assertFalse($user->avatar()->exists());
 
-        $this->artisan(RefreshAvatarCommand::class, ['--id' => $user->id])
-            ->expectsOutputToContain("- ID: {$user->id}")
+        $this->artisan("bookstack:refresh-avatar --id={$user->id} -f")
             ->expectsQuestion('Are you sure you want to proceed?', true)
-            ->expectsOutput('Could not update avatar please review logs.')
-            ->assertExitCode(Command::FAILURE);
+            ->expectsOutput("[ID: {$user->id}] {$user->email} - Not updated")
+            ->assertExitCode(1);
 
         $this->assertEquals(1, $requests->requestCount());
-
-        $user->refresh();
-        $newId = $user->avatar->id ?? $oldId;
-        $this->assertEquals($oldId, $newId);
+        $this->assertFalse($user->avatar()->exists());
     }
 
     public function test_saying_no_to_confirmation_does_not_refresh_avatar()
     {
-        /** @var User $user */
-        $user = User::query()->first();
+        $user = $this->users->viewer();
 
         $this->assertFalse($user->avatar()->exists());
-        $this->artisan(RefreshAvatarCommand::class, ['--id' => $user->id])
+        $this->artisan("bookstack:refresh-avatar --id={$user->id} -f")
             ->expectsQuestion('Are you sure you want to proceed?', false)
-            ->assertExitCode(Command::FAILURE);
+            ->assertExitCode(0);
         $this->assertFalse($user->avatar()->exists());
     }
 
     public function test_giving_non_existing_user_shows_error_message()
     {
-        $this->artisan(RefreshAvatarCommand::class, ['--email' => '[email protected]'])
+        $this->artisan('bookstack:refresh-avatar [email protected]')
             ->expectsOutput('A user where [email protected] could not be found.')
-            ->assertExitCode(Command::FAILURE);
+            ->assertExitCode(1);
     }
 
     public function test_command_runs_all_users_without_avatars_dry_run()
     {
         $users = User::query()->where('image_id', '=', 0)->get();
 
-        $this->artisan(RefreshAvatarCommand::class, ['--users-without-avatars' => true])
-            ->expectsOutput(count($users) . ' user(s) found without avatars.')
-            ->expectsOutput("ID {$users[0]->id} - ")
-            ->expectsOutput('Not updated')
-            ->expectsOutput('Dry run, no avatars have been updated')
-            ->assertExitCode(Command::SUCCESS);
+        $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);
     }
 
-    public function test_command_runs_all_users_without_avatars_non_to_update()
+    public function test_command_runs_all_users_without_avatars_with_none_to_update()
     {
-        config()->set(['services.disable_services' => false]);
-
-        /** @var UserAvatars $avatar */
-        $avatar = app()->make(UserAvatars::class);
-
-        /** @var Collection|User[] $users */
-        $users = User::query()->get();
-        $responses = [];
-        foreach ($users as $user) {
-            $avatar->fetchAndAssignToUser($user);
-            $responses[] = new Response(200, ['Content-Type' => 'image/png'], $this->files->pngImageData());
-        }
-        $requests = $this->mockHttpClient($responses);
+        $requests = $this->mockHttpClient();
+        $image = Image::factory()->create();
+        User::query()->update(['image_id' => $image->id]);
 
-        $this->artisan(RefreshAvatarCommand::class, ['--users-without-avatars' => true, '-f' => true])
-            ->expectsOutput('0 user(s) found without avatars.')
-            ->expectsQuestion('Are you sure you want to refresh avatars of users that do not have one?', true)
-            ->assertExitCode(Command::SUCCESS);
+        $this->artisan('bookstack:refresh-avatar --users-without-avatars -f')
+            ->expectsOutput('0 user(s) found to update avatars for.')
+            ->assertExitCode(0);
 
-        $userWithAvatars = User::query()->where('image_id', '==', 0)->count();
-        $this->assertEquals(0, $userWithAvatars);
         $this->assertEquals(0, $requests->requestCount());
     }
 
     public function test_command_runs_all_users_without_avatars()
     {
-        config()->set(['services.disable_services' => false]);
-
-        /** @var UserAvatars $avatar */
-        $avatar = app()->make(UserAvatars::class);
-
-        /** @var Collection|User[] $users */
-        $users = User::query()->get();
-        foreach ($users as $user) {
-            $avatar->destroyAllForUser($user);
-        }
-
         /** @var Collection|User[] $users */
         $users = User::query()->where('image_id', '=', 0)->get();
 
-        $pendingCommand = $this->artisan(RefreshAvatarCommand::class, ['--users-without-avatars' => true, '-f' => true]);
+        $pendingCommand = $this->artisan('bookstack:refresh-avatar --users-without-avatars -f');
         $pendingCommand
-            ->expectsOutput($users->count() . ' user(s) found without avatars.')
-            ->expectsQuestion('Are you sure you want to refresh avatars of users that do not have one?', true);
+            ->expectsOutput($users->count() . ' user(s) found to update avatars for.')
+            ->expectsQuestion('Are you sure you want to proceed?', true);
 
         $responses = [];
         foreach ($users as $user) {
-            $pendingCommand->expectsOutput("ID {$user->id} - ");
-            $pendingCommand->expectsOutput('Updated');
+            $pendingCommand->expectsOutput("[ID: {$user->id}] {$user->email} - Updated");
             $responses[] = new Response(200, ['Content-Type' => 'image/png'], $this->files->pngImageData());
         }
         $requests = $this->mockHttpClient($responses);
 
-        $pendingCommand->assertExitCode(Command::SUCCESS);
+        $pendingCommand->assertExitCode(0);
         $pendingCommand->run();
 
-        $userWithAvatars = User::query()->where('image_id', '!=', 0)->count();
-        $this->assertEquals($users->count(), $userWithAvatars);
+        $this->assertEquals(0, User::query()->where('image_id', '=', 0)->count());
         $this->assertEquals($users->count(), $requests->requestCount());
     }
 
     public function test_saying_no_to_confirmation_all_users_without_avatars()
     {
-        $requests = $this->mockHttpClient([new Response(200, ['Content-Type' => 'image/png'], $this->files->pngImageData())]);
-        config()->set(['services.disable_services' => false]);
-
-        /** @var UserAvatars $avatar */
-        $avatar = app()->make(UserAvatars::class);
-
-        /** @var Collection|User[] $users */
-        $users = User::query()->get();
-        foreach ($users as $user) {
-            $avatar->destroyAllForUser($user);
-        }
+        $requests = $this->mockHttpClient();
 
-        $this->artisan(RefreshAvatarCommand::class, ['--users-without-avatars' => true, '-f' => true])
-            ->expectsQuestion('Are you sure you want to refresh avatars of users that do not have one?', false)
-            ->assertExitCode(Command::SUCCESS);
+        $this->artisan('bookstack:refresh-avatar --users-without-avatars -f')
+            ->expectsQuestion('Are you sure you want to proceed?', false)
+            ->assertExitCode(0);
 
-        $userWithAvatars = User::query()->where('image_id', '=', 0)->count();
-        $this->assertEquals($users->count(), $userWithAvatars);
         $this->assertEquals(0, $requests->requestCount());
     }
 
@@ -220,98 +170,77 @@ final class RefreshAvatarCommandTest extends TestCase
     {
         $users = User::query()->where('image_id', '=', 0)->get();
 
-        $this->artisan(RefreshAvatarCommand::class, ['--all' => true])
-            ->expectsOutput(count($users) . ' user(s) found.')
-            ->expectsOutput("ID {$users[0]->id} - ")
-            ->expectsOutput('Not updated')
-            ->expectsOutput('Dry run, no avatars have been updated')
-            ->assertExitCode(Command::SUCCESS);
+        $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);
     }
 
     public function test_command_runs_update_all_users_avatar()
     {
-        config()->set(['services.disable_services' => false]);
-
         /** @var Collection|User[] $users */
         $users = User::query()->get();
 
-        $pendingCommand = $this->artisan(RefreshAvatarCommand::class, ['--all' => true, '-f' => true]);
+        $pendingCommand = $this->artisan('bookstack:refresh-avatar --all -f');
         $pendingCommand
-            ->expectsOutput($users->count() . ' user(s) found.')
-            ->expectsQuestion('Are you sure you want to refresh avatars for ALL USERS?', true);
+            ->expectsOutput($users->count() . ' user(s) found to update avatars for.')
+            ->expectsQuestion('Are you sure you want to proceed?', true);
 
         $responses = [];
         foreach ($users as $user) {
-            $pendingCommand->expectsOutput("ID {$user->id} - ");
-            $pendingCommand->expectsOutput('Updated');
+            $pendingCommand->expectsOutput("[ID: {$user->id}] {$user->email} - Updated");
             $responses[] = new Response(200, ['Content-Type' => 'image/png'], $this->files->pngImageData());
         }
         $requests = $this->mockHttpClient($responses);
 
-        $pendingCommand->assertExitCode(Command::SUCCESS);
+        $pendingCommand->assertExitCode(0);
         $pendingCommand->run();
 
-        $userWithAvatars = User::query()->where('image_id', '!=', 0)->count();
-        $this->assertEquals($users->count(), $userWithAvatars);
+        $this->assertEquals(0, User::query()->where('image_id', '=', 0)->count());
         $this->assertEquals($users->count(), $requests->requestCount());
     }
 
     public function test_command_runs_update_all_users_avatar_errors()
     {
-        config()->set(['services.disable_services' => false]);
-
         /** @var Collection|User[] $users */
-        $users = User::query()->get();
+        $users = array_values(User::query()->get()->all());
 
-        $pendingCommand = $this->artisan(RefreshAvatarCommand::class, ['--all' => true, '-f' => true]);
+        $pendingCommand = $this->artisan('bookstack:refresh-avatar --all -f');
         $pendingCommand
-            ->expectsOutput($users->count() . ' user(s) found.')
-            ->expectsQuestion('Are you sure you want to refresh avatars for ALL USERS?', true);
+            ->expectsOutput(count($users) . ' user(s) found to update avatars for.')
+            ->expectsQuestion('Are you sure you want to proceed?', true);
 
         $responses = [];
-        foreach ($users as $key => $user) {
-            $pendingCommand->expectsOutput("ID {$user->id} - ");
-
-            if ($key == 1) {
-                $pendingCommand->expectsOutput('Not updated');
+        foreach ($users as $index => $user) {
+            if ($index === 0) {
+                $pendingCommand->expectsOutput("[ID: {$user->id}] {$user->email} - Not updated");
                 $responses[] = new Response(404);
                 continue;
             }
 
-            $pendingCommand->expectsOutput('Updated');
+            $pendingCommand->expectsOutput("[ID: {$user->id}] {$user->email} - Updated");
             $responses[] = new Response(200, ['Content-Type' => 'image/png'], $this->files->pngImageData());
         }
 
         $requests = $this->mockHttpClient($responses);
 
-        $pendingCommand->assertExitCode(Command::FAILURE);
+        $pendingCommand->assertExitCode(1);
         $pendingCommand->run();
 
         $userWithAvatars = User::query()->where('image_id', '!=', 0)->count();
-        $this->assertEquals($users->count() - 1, $userWithAvatars);
-        $this->assertEquals($users->count(), $requests->requestCount());
+        $this->assertEquals(count($users) - 1, $userWithAvatars);
+        $this->assertEquals(count($users), $requests->requestCount());
     }
 
     public function test_saying_no_to_confirmation_update_all_users_avatar()
     {
         $requests = $this->mockHttpClient([new Response(200, ['Content-Type' => 'image/png'], $this->files->pngImageData())]);
-        config()->set(['services.disable_services' => false]);
 
-        /** @var UserAvatars $avatar */
-        $avatar = app()->make(UserAvatars::class);
-
-        /** @var Collection|User[] $users */
-        $users = User::query()->get();
-        foreach ($users as $user) {
-            $avatar->destroyAllForUser($user);
-        }
-
-        $this->artisan(RefreshAvatarCommand::class, ['--all' => true, '-f' => true])
-            ->expectsQuestion('Are you sure you want to refresh avatars for ALL USERS?', false)
-            ->assertExitCode(Command::SUCCESS);
+        $this->artisan('bookstack:refresh-avatar --all -f')
+            ->expectsQuestion('Are you sure you want to proceed?', false)
+            ->assertExitCode(0);
 
-        $userWithAvatars = User::query()->where('image_id', '=', 0)->count();
-        $this->assertEquals($users->count(), $userWithAvatars);
         $this->assertEquals(0, $requests->requestCount());
     }
 }