whisper-money/tests/Feature/Settings/BudgetNotificationPreferenc...

114 lines
4.0 KiB
PHP

<?php
use App\Models\Budget;
use App\Models\Category;
use App\Models\User;
use App\Models\UserSetting;
test('notifications page lists the user budgets and defaults', function () {
$user = User::factory()->create();
Budget::factory()->create(['user_id' => $user->id, 'name' => 'Padel']);
$response = $this->actingAs($user)->get(route('notifications.index'));
$response->assertOk();
$response->assertInertia(fn ($page) => $page
->component('settings/notifications')
->has('budgets', 1)
->where('budgetDefaults.notify_on_new_transaction', false)
->where('budgetDefaults.notify_on_close_to_limit', true)
->where('budgetDefaults.notify_on_over_limit', true)
->where('budgets.0.name', 'Padel'));
});
test('a settings row created without the budget columns leaves the per-transaction default off', function () {
$user = User::factory()->create();
// Every settings controller writes only its own column, so the rest of the
// row falls back to the database defaults.
$user->setting()->updateOrCreate(
['user_id' => $user->id],
['notify_on_bank_transactions_synced' => true],
);
expect($user->fresh()->setting)
->budget_notify_on_new_transaction->toBeFalse()
->budget_notify_on_close_to_limit->toBeTrue()
->budget_notify_on_over_limit->toBeTrue();
});
test('a budget notification toggle can be updated', function () {
$user = User::factory()->create();
$budget = Budget::factory()->create([
'user_id' => $user->id,
'notify_on_over_limit' => false,
]);
$this->actingAs($user)
->patch(route('notifications.budgets.update', $budget), [
'notify_on_over_limit' => true,
])
->assertSessionHasNoErrors();
expect($budget->fresh()->notify_on_over_limit)->toBeTrue();
});
test('a user cannot update another user budget notifications', function () {
$owner = User::factory()->create();
$intruder = User::factory()->create();
$budget = Budget::factory()->create(['user_id' => $owner->id]);
$this->actingAs($intruder)
->patch(route('notifications.budgets.update', $budget), [
'notify_on_over_limit' => true,
])
->assertForbidden();
expect($budget->fresh()->notify_on_over_limit)->toBeFalse();
});
test('a new budget enables the limit notifications by default but not the per-transaction one', function () {
$user = User::factory()->create(['onboarded_at' => now()]);
$category = Category::factory()->create(['user_id' => $user->id]);
$this->actingAs($user)->post('/budgets', [
'name' => 'Default Budget',
'period_type' => 'monthly',
'period_start_day' => 1,
'category_ids' => [$category->id],
'rollover_type' => 'reset',
'allocated_amount' => 100000,
])->assertRedirect();
$budget = Budget::where('user_id', $user->id)->firstOrFail();
expect($budget->notify_on_new_transaction)->toBeFalse()
->and($budget->notify_on_close_to_limit)->toBeTrue()
->and($budget->notify_on_over_limit)->toBeTrue();
});
test('a new budget inherits the user notification defaults', function () {
$user = User::factory()->create(['onboarded_at' => now()]);
UserSetting::factory()->for($user)->create([
'budget_notify_on_new_transaction' => true,
'budget_notify_on_close_to_limit' => false,
'budget_notify_on_over_limit' => true,
]);
$category = Category::factory()->create(['user_id' => $user->id]);
$this->actingAs($user)->post('/budgets', [
'name' => 'Inherited Budget',
'period_type' => 'monthly',
'period_start_day' => 1,
'category_ids' => [$category->id],
'rollover_type' => 'reset',
'allocated_amount' => 100000,
])->assertRedirect();
$budget = Budget::where('user_id', $user->id)->firstOrFail();
expect($budget->notify_on_new_transaction)->toBeTrue()
->and($budget->notify_on_close_to_limit)->toBeFalse()
->and($budget->notify_on_over_limit)->toBeTrue();
});