X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/ea7592509f61605b84959d39d74757e962501609..refs/pull/5405/head:/tests/Commands/RefreshAvatarCommandTest.php diff --git a/tests/Commands/RefreshAvatarCommandTest.php b/tests/Commands/RefreshAvatarCommandTest.php index d625097ef..6126f21a8 100644 --- a/tests/Commands/RefreshAvatarCommandTest.php +++ b/tests/Commands/RefreshAvatarCommandTest.php @@ -1,47 +1,55 @@ 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= or --email= option must be provided.') - ->assertExitCode(Command::FAILURE); + $this->artisan('bookstack:refresh-avatar') + ->expectsOutputToContain("Either a --id= or --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' => 'donkeys@example.com']) + $this->artisan('bookstack:refresh-avatar --email=donkeys@example.com') ->expectsOutput('A user where email=donkeys@example.com 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()); } }