Skip to content

Commit b51babd

Browse files
committed
Refactor FortifyServiceProvider and add UpdateUserProfileInformationTest for profile update functionality
1 parent db89cb2 commit b51babd

File tree

2 files changed

+236
-2
lines changed

2 files changed

+236
-2
lines changed

app/Providers/FortifyServiceProvider.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@ final class FortifyServiceProvider extends ServiceProvider
2323
*/
2424
public function register(): void
2525
{
26-
Fortify::ignoreRoutes();
27-
2826
$this->app->singleton(CreatesNewSocialUsers::class, CreateNewSocialUser::class);
2927
}
3028

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use App\Actions\Fortify\UpdateUserProfileInformation;
6+
use App\Models\User;
7+
use Illuminate\Http\UploadedFile;
8+
use Illuminate\Support\Facades\Notification;
9+
use Illuminate\Support\Facades\Storage;
10+
use Illuminate\Validation\ValidationException;
11+
12+
beforeEach(function () {
13+
$this->action = new UpdateUserProfileInformation;
14+
$this->user = User::factory()->create([
15+
'name' => 'John Doe',
16+
'email' => '[email protected]',
17+
'email_verified_at' => now(),
18+
]);
19+
});
20+
21+
describe('basic profile updates', function () {
22+
test('can update name and email', function () {
23+
$this->action->update($this->user, [
24+
'name' => 'Jane Smith',
25+
'email' => '[email protected]',
26+
]);
27+
28+
expect($this->user->fresh())
29+
->name->toBe('Jane Smith')
30+
->email->toBe('[email protected]')
31+
->email_verified_at->toBeNull();
32+
});
33+
34+
test('can update name without changing email', function () {
35+
$originalVerification = $this->user->email_verified_at;
36+
37+
$this->action->update($this->user, [
38+
'name' => 'Jane Smith',
39+
'email' => $this->user->email,
40+
]);
41+
42+
expect($this->user->fresh())
43+
->name->toBe('Jane Smith')
44+
->email->toBe('[email protected]')
45+
->email_verified_at->toEqual($originalVerification);
46+
});
47+
48+
test('can update with null photo', function () {
49+
$this->action->update($this->user, [
50+
'name' => 'Updated Name',
51+
'email' => $this->user->email,
52+
'photo' => null,
53+
]);
54+
55+
expect($this->user->fresh())->name->toBe('Updated Name');
56+
});
57+
});
58+
59+
describe('email verification logic', function () {
60+
test('resets verification when email changes', function () {
61+
$this->action->update($this->user, [
62+
'name' => $this->user->name,
63+
'email' => '[email protected]',
64+
]);
65+
66+
expect($this->user->fresh())
67+
->email->toBe('[email protected]')
68+
->email_verified_at->toBeNull();
69+
});
70+
71+
test('sends verification notification when email changes', function () {
72+
Notification::fake();
73+
74+
$this->action->update($this->user, [
75+
'name' => $this->user->name,
76+
'email' => '[email protected]',
77+
]);
78+
79+
Notification::assertSentTo($this->user, \Illuminate\Auth\Notifications\VerifyEmail::class);
80+
});
81+
82+
test('preserves verification when email stays same', function () {
83+
$originalVerification = $this->user->email_verified_at;
84+
85+
$this->action->update($this->user, [
86+
'name' => 'New Name',
87+
'email' => $this->user->email,
88+
]);
89+
90+
expect($this->user->fresh()->email_verified_at)->toEqual($originalVerification);
91+
});
92+
});
93+
94+
describe('photo upload', function () {
95+
beforeEach(fn () => Storage::fake('public'));
96+
97+
test('can upload valid photo', function ($format) {
98+
$photo = UploadedFile::fake()->image("avatar.{$format}", 300, 300);
99+
100+
$this->action->update($this->user, [
101+
'name' => $this->user->name,
102+
'email' => $this->user->email,
103+
'photo' => $photo,
104+
]);
105+
106+
$user = $this->user->fresh();
107+
expect($user->profile_photo_path)->not->toBeNull()
108+
->and(Storage::disk('public')->exists($user->profile_photo_path))->toBeTrue();
109+
})->with(['jpg', 'jpeg', 'png']);
110+
111+
test('handles photo with email change', function () {
112+
Notification::fake();
113+
$photo = UploadedFile::fake()->image('avatar.png', 400, 400);
114+
115+
$this->action->update($this->user, [
116+
'name' => 'Photo User',
117+
'email' => '[email protected]',
118+
'photo' => $photo,
119+
]);
120+
121+
expect($this->user->fresh())
122+
->name->toBe('Photo User')
123+
->email->toBe('[email protected]')
124+
->email_verified_at->toBeNull()
125+
->profile_photo_path->not->toBeNull();
126+
127+
Notification::assertSentTo($this->user, \Illuminate\Auth\Notifications\VerifyEmail::class);
128+
});
129+
});
130+
131+
describe('validation', function () {
132+
test('validates required fields', function ($field, $value) {
133+
$input = [
134+
'name' => 'Valid Name',
135+
'email' => '[email protected]',
136+
];
137+
$input[$field] = $value;
138+
139+
expect(fn () => $this->action->update($this->user, $input))
140+
->toThrow(ValidationException::class);
141+
})->with([
142+
'empty name' => ['name', ''],
143+
'invalid email' => ['email', 'invalid-email'],
144+
'long name' => ['name', str_repeat('a', 256)],
145+
'long email' => ['email', str_repeat('a', 250).'@example.com'],
146+
]);
147+
148+
test('validates invalid photo file type', function () {
149+
Storage::fake('public');
150+
$photo = UploadedFile::fake()->create('document.pdf', 100);
151+
152+
expect(fn () => $this->action->update($this->user, [
153+
'name' => $this->user->name,
154+
'email' => $this->user->email,
155+
'photo' => $photo,
156+
]))->toThrow(ValidationException::class);
157+
});
158+
159+
test('validates photo file size limit', function () {
160+
Storage::fake('public');
161+
$photo = UploadedFile::fake()->image('avatar.jpg')->size(1025);
162+
163+
expect(fn () => $this->action->update($this->user, [
164+
'name' => $this->user->name,
165+
'email' => $this->user->email,
166+
'photo' => $photo,
167+
]))->toThrow(ValidationException::class);
168+
});
169+
170+
test('rejects duplicate email', function () {
171+
User::factory()->create(['email' => '[email protected]']);
172+
173+
expect(fn () => $this->action->update($this->user, [
174+
'name' => $this->user->name,
175+
'email' => '[email protected]',
176+
]))->toThrow(ValidationException::class);
177+
});
178+
179+
test('allows user to keep same email', function () {
180+
expect(fn () => $this->action->update($this->user, [
181+
'name' => 'Updated Name',
182+
'email' => $this->user->email,
183+
]))->not->toThrow(ValidationException::class);
184+
});
185+
186+
test('uses correct error bag', function () {
187+
try {
188+
$this->action->update($this->user, ['name' => '', 'email' => 'invalid']);
189+
} catch (ValidationException $e) {
190+
expect($e->errorBag)->toBe('updateProfileInformation')
191+
->and($e->validator->errors()->toArray())
192+
->toHaveKey('name')
193+
->toHaveKey('email');
194+
}
195+
});
196+
197+
test('accepts boundary values', function () {
198+
Storage::fake('public');
199+
$name255 = str_repeat('a', 255);
200+
$email255 = str_repeat('a', 243).'@example.com';
201+
$photo1024 = UploadedFile::fake()->image('avatar.jpg')->size(1024);
202+
203+
expect(fn () => $this->action->update($this->user, [
204+
'name' => $name255,
205+
'email' => $email255,
206+
'photo' => $photo1024,
207+
]))->not->toThrow(ValidationException::class);
208+
209+
expect($this->user->fresh())
210+
->name->toBe($name255)
211+
->email->toBe($email255);
212+
});
213+
214+
test('validates missing required fields', function () {
215+
expect(fn () => $this->action->update($this->user, []))
216+
->toThrow(ValidationException::class);
217+
});
218+
});
219+
220+
describe('complex scenarios', function () {
221+
test('handles complete profile overhaul', function () {
222+
Storage::fake('public');
223+
$originalVerification = $this->user->email_verified_at;
224+
225+
$this->action->update($this->user, [
226+
'name' => 'Completely New Name',
227+
'email' => '[email protected]',
228+
]);
229+
230+
expect($this->user->fresh())
231+
->name->toBe('Completely New Name')
232+
->email->toBe('[email protected]')
233+
->email_verified_at->toBeNull()
234+
->email_verified_at->not->toEqual($originalVerification);
235+
});
236+
});

0 commit comments

Comments
 (0)