Files
portal/app/tests/Feature/Auth/NotificationPreferencesTest.php
T

151 lines
5.7 KiB
PHP
Raw Normal View History

<?php
declare(strict_types=1);
use App\Models\Tenant;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
/**
* Тесты PATCH /api/auth/me/notification-preferences (Settings → Уведомления).
*
* Принимает {prefs: {event: {channel: bool}}, sound_enabled?: bool}.
* Валидация: события ∈ ALL_EVENTS (8), каналы ∈ {inapp, push, email}.
* Незадекларированные ключи отбрасываются (защита от schema-pollution).
*/
uses(DatabaseTransactions::class);
beforeEach(function () {
$this->tenant = Tenant::factory()->create();
$this->user = User::factory()->create(['tenant_id' => $this->tenant->id]);
$this->actingAs($this->user);
});
test('PATCH без auth: 401', function () {
auth()->logout();
$this->patchJson('/api/auth/me/notification-preferences', [
'prefs' => ['new_lead' => ['email' => true]],
])->assertStatus(401);
});
test('PATCH успех: сохраняет prefs + возвращает user', function () {
$response = $this->patchJson('/api/auth/me/notification-preferences', [
'prefs' => [
'new_lead' => ['inapp' => true, 'push' => false, 'email' => true],
'reminder' => ['inapp' => true, 'email' => true],
],
'sound_enabled' => false,
]);
$response->assertOk();
$userResp = $response->json('user');
expect($userResp['notification_preferences']['new_lead']['email'])->toBeTrue();
expect($userResp['notification_preferences']['new_lead']['inapp'])->toBeTrue();
expect($userResp['notification_preferences']['new_lead']['push'])->toBeFalse();
expect($userResp['sound_enabled'])->toBeFalse();
});
test('PATCH: неизвестные events отбрасываются', function () {
$response = $this->patchJson('/api/auth/me/notification-preferences', [
'prefs' => [
'new_lead' => ['email' => true],
'fake_event' => ['email' => true], // не в ALL_EVENTS — должно отброситься
],
]);
$response->assertOk();
$prefs = $response->json('user.notification_preferences');
expect($prefs)->toHaveKey('new_lead');
expect($prefs)->not->toHaveKey('fake_event');
});
test('PATCH: неизвестные каналы отбрасываются', function () {
$response = $this->patchJson('/api/auth/me/notification-preferences', [
'prefs' => [
'new_lead' => [
'email' => true,
'sms' => true, // SMS — не в нашей schema
'webhook' => true, // тоже не из schema
],
],
]);
$response->assertOk();
$prefs = $response->json('user.notification_preferences.new_lead');
expect($prefs)->toHaveKey('email');
expect($prefs)->not->toHaveKey('sms');
expect($prefs)->not->toHaveKey('webhook');
});
test('PATCH: 422 без prefs', function () {
$this->patchJson('/api/auth/me/notification-preferences', [
'sound_enabled' => true,
])->assertStatus(422);
});
test('PATCH: sound_enabled опционален (без него не меняется)', function () {
$this->user->update(['sound_enabled' => true]);
$response = $this->patchJson('/api/auth/me/notification-preferences', [
'prefs' => ['new_lead' => ['email' => true]],
]);
$response->assertOk();
expect($response->json('user.sound_enabled'))->toBeTrue();
});
test('GET /api/auth/me возвращает notification_preferences + sound_enabled', function () {
$response = $this->getJson('/api/auth/me');
$response->assertOk();
$user = $response->json('user');
expect($user)->toHaveKey('notification_preferences');
expect($user)->toHaveKey('sound_enabled');
// schema-default: 8 events.
expect($user['notification_preferences'])->toHaveKey('new_lead');
expect($user['notification_preferences'])->toHaveKey('reminder');
expect($user['notification_preferences'])->toHaveKey('low_balance');
});
test('PATCH: prefs.* должен быть объект (не строка)', function () {
$this->patchJson('/api/auth/me/notification-preferences', [
'prefs' => [
'new_lead' => 'true', // строка вместо объекта
],
])->assertStatus(422);
});
test('PATCH: bool-значения каналов кастятся', function () {
$response = $this->patchJson('/api/auth/me/notification-preferences', [
'prefs' => [
'new_lead' => ['email' => 1, 'inapp' => 0, 'push' => '1'],
],
]);
$response->assertOk();
$prefs = $response->json('user.notification_preferences.new_lead');
expect($prefs['email'])->toBeTrue();
expect($prefs['inapp'])->toBeFalse();
expect($prefs['push'])->toBeTrue();
});
test('PATCH полностью замещает prefs (не merge): ранее сохранённые отсутствующие events исчезают', function () {
// Дано: user имеет полный default-набор (schema-default 8 events).
$this->user->update(['notification_preferences' => [
'new_lead' => ['email' => true],
'reminder' => ['email' => true],
'low_balance' => ['email' => true],
]]);
// Update только new_lead — остальные пропадают (replace-семантика).
$response = $this->patchJson('/api/auth/me/notification-preferences', [
'prefs' => ['new_lead' => ['email' => false]],
]);
$response->assertOk();
$prefs = $response->json('user.notification_preferences');
expect($prefs)->toHaveKey('new_lead');
expect($prefs)->not->toHaveKey('reminder');
expect($prefs)->not->toHaveKey('low_balance');
});