]> BookStack Code Mirror - bookstack/blob - tests/Commands/RefreshAvatarCommandTest.php
Tests: Updated failing license test
[bookstack] / tests / Commands / RefreshAvatarCommandTest.php
1 <?php
2
3 namespace Tests\Commands;
4
5 use BookStack\Uploads\Image;
6 use BookStack\Users\Models\User;
7 use GuzzleHttp\Psr7\Response;
8 use Illuminate\Database\Eloquent\Collection;
9 use Tests\TestCase;
10
11 class RefreshAvatarCommandTest extends TestCase
12 {
13     public function setUp(): void
14     {
15         parent::setUp();
16
17         config()->set([
18             'services.disable_services' => false,
19             'services.avatar_url' => 'https://avatars.example.com?a=b',
20         ]);
21     }
22
23     public function test_command_errors_if_avatar_fetch_disabled()
24     {
25         config()->set(['services.avatar_url' => false]);
26
27         $this->artisan('bookstack:refresh-avatar')
28             ->expectsOutputToContain("Avatar fetching is disabled on this instance")
29             ->assertExitCode(1);
30     }
31
32     public function test_command_requires_email_or_id_option()
33     {
34         $this->artisan('bookstack:refresh-avatar')
35             ->expectsOutputToContain("Either a --id=<number> or --email=<email> option must be provided")
36             ->assertExitCode(1);
37     }
38
39     public function test_command_runs_with_provided_email()
40     {
41         $requests = $this->mockHttpClient([new Response(200, ['Content-Type' => 'image/png'], $this->files->pngImageData())]);
42
43         $user = $this->users->viewer();
44         $this->assertFalse($user->avatar()->exists());
45
46         $this->artisan("bookstack:refresh-avatar --email={$user->email} -f")
47             ->expectsQuestion('Are you sure you want to proceed?', true)
48             ->expectsOutput("[ID: {$user->id}] {$user->email} - Updated")
49             ->expectsOutputToContain('This will destroy any existing avatar images these users have, and attempt to fetch new avatar images from avatars.example.com')
50             ->assertExitCode(0);
51
52         $this->assertEquals('https://avatars.example.com?a=b', $requests->latestRequest()->getUri());
53
54         $user->refresh();
55         $this->assertTrue($user->avatar()->exists());
56     }
57
58     public function test_command_runs_with_provided_id()
59     {
60         $requests = $this->mockHttpClient([new Response(200, ['Content-Type' => 'image/png'], $this->files->pngImageData())]);
61
62         $user = $this->users->viewer();
63         $this->assertFalse($user->avatar()->exists());
64
65         $this->artisan("bookstack:refresh-avatar --id={$user->id} -f")
66             ->expectsQuestion('Are you sure you want to proceed?', true)
67             ->expectsOutput("[ID: {$user->id}] {$user->email} - Updated")
68             ->assertExitCode(0);
69
70         $this->assertEquals('https://avatars.example.com?a=b', $requests->latestRequest()->getUri());
71
72         $user->refresh();
73         $this->assertTrue($user->avatar()->exists());
74     }
75
76     public function test_command_runs_with_provided_id_error_upstream()
77     {
78         $requests = $this->mockHttpClient([new Response(404)]);
79
80         $user = $this->users->viewer();
81         $this->assertFalse($user->avatar()->exists());
82
83         $this->artisan("bookstack:refresh-avatar --id={$user->id} -f")
84             ->expectsQuestion('Are you sure you want to proceed?', true)
85             ->expectsOutput("[ID: {$user->id}] {$user->email} - Not updated")
86             ->assertExitCode(1);
87
88         $this->assertEquals(1, $requests->requestCount());
89         $this->assertFalse($user->avatar()->exists());
90     }
91
92     public function test_saying_no_to_confirmation_does_not_refresh_avatar()
93     {
94         $user = $this->users->viewer();
95
96         $this->assertFalse($user->avatar()->exists());
97         $this->artisan("bookstack:refresh-avatar --id={$user->id} -f")
98             ->expectsQuestion('Are you sure you want to proceed?', false)
99             ->assertExitCode(0);
100         $this->assertFalse($user->avatar()->exists());
101     }
102
103     public function test_giving_non_existing_user_shows_error_message()
104     {
105         $this->artisan('bookstack:refresh-avatar [email protected]')
106             ->expectsOutput('A user where [email protected] could not be found.')
107             ->assertExitCode(1);
108     }
109
110     public function test_command_runs_all_users_without_avatars_dry_run()
111     {
112         $users = User::query()->where('image_id', '=', 0)->get();
113
114         $this->artisan('bookstack:refresh-avatar --users-without-avatars')
115             ->expectsOutput(count($users) . ' user(s) found to update avatars for.')
116             ->expectsOutput("[ID: {$users[0]->id}] {$users[0]->email} - Not updated")
117             ->expectsOutput('Dry run, no avatars were updated.')
118             ->assertExitCode(0);
119     }
120
121     public function test_command_runs_all_users_without_avatars_with_none_to_update()
122     {
123         $requests = $this->mockHttpClient();
124         $image = Image::factory()->create();
125         User::query()->update(['image_id' => $image->id]);
126
127         $this->artisan('bookstack:refresh-avatar --users-without-avatars -f')
128             ->expectsOutput('0 user(s) found to update avatars for.')
129             ->assertExitCode(0);
130
131         $this->assertEquals(0, $requests->requestCount());
132     }
133
134     public function test_command_runs_all_users_without_avatars()
135     {
136         /** @var Collection|User[] $users */
137         $users = User::query()->where('image_id', '=', 0)->get();
138
139         $pendingCommand = $this->artisan('bookstack:refresh-avatar --users-without-avatars -f');
140         $pendingCommand
141             ->expectsOutput($users->count() . ' user(s) found to update avatars for.')
142             ->expectsQuestion('Are you sure you want to proceed?', true);
143
144         $responses = [];
145         foreach ($users as $user) {
146             $pendingCommand->expectsOutput("[ID: {$user->id}] {$user->email} - Updated");
147             $responses[] = new Response(200, ['Content-Type' => 'image/png'], $this->files->pngImageData());
148         }
149         $requests = $this->mockHttpClient($responses);
150
151         $pendingCommand->assertExitCode(0);
152         $pendingCommand->run();
153
154         $this->assertEquals(0, User::query()->where('image_id', '=', 0)->count());
155         $this->assertEquals($users->count(), $requests->requestCount());
156     }
157
158     public function test_saying_no_to_confirmation_all_users_without_avatars()
159     {
160         $requests = $this->mockHttpClient();
161
162         $this->artisan('bookstack:refresh-avatar --users-without-avatars -f')
163             ->expectsQuestion('Are you sure you want to proceed?', false)
164             ->assertExitCode(0);
165
166         $this->assertEquals(0, $requests->requestCount());
167     }
168
169     public function test_command_runs_all_users_dry_run()
170     {
171         $users = User::query()->where('image_id', '=', 0)->get();
172
173         $this->artisan('bookstack:refresh-avatar --all')
174             ->expectsOutput(count($users) . ' user(s) found to update avatars for.')
175             ->expectsOutput("[ID: {$users[0]->id}] {$users[0]->email} - Not updated")
176             ->expectsOutput('Dry run, no avatars were updated.')
177             ->assertExitCode(0);
178     }
179
180     public function test_command_runs_update_all_users_avatar()
181     {
182         /** @var Collection|User[] $users */
183         $users = User::query()->get();
184
185         $pendingCommand = $this->artisan('bookstack:refresh-avatar --all -f');
186         $pendingCommand
187             ->expectsOutput($users->count() . ' user(s) found to update avatars for.')
188             ->expectsQuestion('Are you sure you want to proceed?', true);
189
190         $responses = [];
191         foreach ($users as $user) {
192             $pendingCommand->expectsOutput("[ID: {$user->id}] {$user->email} - Updated");
193             $responses[] = new Response(200, ['Content-Type' => 'image/png'], $this->files->pngImageData());
194         }
195         $requests = $this->mockHttpClient($responses);
196
197         $pendingCommand->assertExitCode(0);
198         $pendingCommand->run();
199
200         $this->assertEquals(0, User::query()->where('image_id', '=', 0)->count());
201         $this->assertEquals($users->count(), $requests->requestCount());
202     }
203
204     public function test_command_runs_update_all_users_avatar_errors()
205     {
206         /** @var Collection|User[] $users */
207         $users = array_values(User::query()->get()->all());
208
209         $pendingCommand = $this->artisan('bookstack:refresh-avatar --all -f');
210         $pendingCommand
211             ->expectsOutput(count($users) . ' user(s) found to update avatars for.')
212             ->expectsQuestion('Are you sure you want to proceed?', true);
213
214         $responses = [];
215         foreach ($users as $index => $user) {
216             if ($index === 0) {
217                 $pendingCommand->expectsOutput("[ID: {$user->id}] {$user->email} - Not updated");
218                 $responses[] = new Response(404);
219                 continue;
220             }
221
222             $pendingCommand->expectsOutput("[ID: {$user->id}] {$user->email} - Updated");
223             $responses[] = new Response(200, ['Content-Type' => 'image/png'], $this->files->pngImageData());
224         }
225
226         $requests = $this->mockHttpClient($responses);
227
228         $pendingCommand->assertExitCode(1);
229         $pendingCommand->run();
230
231         $userWithAvatars = User::query()->where('image_id', '!=', 0)->count();
232         $this->assertEquals(count($users) - 1, $userWithAvatars);
233         $this->assertEquals(count($users), $requests->requestCount());
234     }
235
236     public function test_saying_no_to_confirmation_update_all_users_avatar()
237     {
238         $requests = $this->mockHttpClient([new Response(200, ['Content-Type' => 'image/png'], $this->files->pngImageData())]);
239
240         $this->artisan('bookstack:refresh-avatar --all -f')
241             ->expectsQuestion('Are you sure you want to proceed?', false)
242             ->assertExitCode(0);
243
244         $this->assertEquals(0, $requests->requestCount());
245     }
246 }