d8d2f37598
Audit J6: ProfileTab needs a full-profile update endpoint. Adds AuthController::updateProfile (first_name/last_name/phone/timezone), routed in the existing /api/auth auth:sanctum group; mirrors the sibling updateNotificationPreferences. userResource() now also returns phone + timezone so the GET /me round-trip carries them. phpstan-baseline.neon updated for Pest PendingCalls false positives in the new test file (same pattern as all other Feature test files). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
82 lines
2.7 KiB
PHP
82 lines
2.7 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Models\Tenant;
|
|
use App\Models\User;
|
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
|
|
|
uses(DatabaseTransactions::class);
|
|
|
|
beforeEach(function () {
|
|
$this->tenant = Tenant::factory()->create();
|
|
$this->user = User::factory()->create([
|
|
'tenant_id' => $this->tenant->id,
|
|
'first_name' => 'Новый',
|
|
'last_name' => 'Пользователь',
|
|
'phone' => null,
|
|
'timezone' => 'Europe/Moscow',
|
|
]);
|
|
$this->actingAs($this->user);
|
|
});
|
|
|
|
test('PATCH /api/auth/me обновляет профиль и возвращает user', function () {
|
|
$response = $this->patchJson('/api/auth/me', [
|
|
'first_name' => 'Иван',
|
|
'last_name' => 'Петров',
|
|
'phone' => '+7 916 000-00-00',
|
|
'timezone' => 'Asia/Yekaterinburg',
|
|
]);
|
|
|
|
$response->assertOk();
|
|
expect($response->json('user.first_name'))->toBe('Иван');
|
|
expect($response->json('user.last_name'))->toBe('Петров');
|
|
expect($response->json('user.phone'))->toBe('+7 916 000-00-00');
|
|
expect($response->json('user.timezone'))->toBe('Asia/Yekaterinburg');
|
|
|
|
$this->user->refresh();
|
|
expect($this->user->first_name)->toBe('Иван');
|
|
expect($this->user->timezone)->toBe('Asia/Yekaterinburg');
|
|
});
|
|
|
|
test('PATCH /api/auth/me без auth: 401', function () {
|
|
auth()->logout();
|
|
$this->patchJson('/api/auth/me', [
|
|
'first_name' => 'Иван',
|
|
'last_name' => 'Петров',
|
|
'timezone' => 'Europe/Moscow',
|
|
])->assertStatus(401);
|
|
});
|
|
|
|
test('PATCH /api/auth/me: 422 при пустом first_name', function () {
|
|
$this->patchJson('/api/auth/me', [
|
|
'first_name' => '',
|
|
'last_name' => 'Петров',
|
|
'timezone' => 'Europe/Moscow',
|
|
])->assertStatus(422)->assertJsonValidationErrorFor('first_name');
|
|
});
|
|
|
|
test('PATCH /api/auth/me: 422 при невалидной timezone', function () {
|
|
$this->patchJson('/api/auth/me', [
|
|
'first_name' => 'Иван',
|
|
'last_name' => 'Петров',
|
|
'timezone' => 'Mars/Olympus',
|
|
])->assertStatus(422)->assertJsonValidationErrorFor('timezone');
|
|
});
|
|
|
|
test('PATCH /api/auth/me: phone опционален (nullable)', function () {
|
|
$response = $this->patchJson('/api/auth/me', [
|
|
'first_name' => 'Иван',
|
|
'last_name' => 'Петров',
|
|
'timezone' => 'Europe/Moscow',
|
|
]);
|
|
$response->assertOk();
|
|
expect($response->json('user.phone'))->toBeNull();
|
|
});
|
|
|
|
test('GET /api/auth/me возвращает phone и timezone', function () {
|
|
$response = $this->getJson('/api/auth/me');
|
|
$response->assertOk();
|
|
expect($response->json('user'))->toHaveKeys(['phone', 'timezone']);
|
|
});
|