test: expand browser coverage for accounts and linked loans (#277)

## Summary
- add browser coverage for manual loan account creation with balance and
loan details
- add browser coverage for creating real-estate accounts linked to
existing loan accounts
- add browser coverage for updating balances and linking or unlinking
loans from account details

## Testing
- php artisan test --compact tests/Browser/BankAccountsTest.php
tests/Browser/AccountsPageTest.php
This commit is contained in:
Víctor Falcón 2026-04-13 09:33:18 +01:00 committed by GitHub
parent d91d9d3b3e
commit dc41c5f6e0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 264 additions and 0 deletions

View File

@ -2,7 +2,10 @@
use App\Enums\AccountType;
use App\Models\Account;
use App\Models\AccountBalance;
use App\Models\Bank;
use App\Models\LoanDetail;
use App\Models\RealEstateDetail;
use App\Models\User;
use function Pest\Laravel\actingAs;
@ -109,6 +112,143 @@ it('can navigate to account details page', function () {
->assertNoJavascriptErrors();
});
it('can update and view balance history from account details page', function () {
$user = User::factory()->onboarded()->create();
$user->update(['currency_code' => 'EUR']);
$bank = Bank::factory()->create(['name' => 'Balance Bank', 'logo' => null]);
$account = Account::factory()->create([
'user_id' => $user->id,
'bank_id' => $bank->id,
'name' => 'Tracked Checking',
'type' => AccountType::Checking,
'currency_code' => 'EUR',
]);
AccountBalance::factory()->create([
'account_id' => $account->id,
'balance_date' => '2024-01-01',
'balance' => 10000000,
]);
actingAs($user);
$page = visit('/accounts');
$page->navigate('/accounts', ['waitUntil' => 'domcontentloaded'])->wait(2);
$page->waitForText('Tracked Checking')
->click('Details →')
->wait(2)
->assertSee('Import balances')
->click('Update balance')
->wait(1)
->fill('#balance-amount', '120000.00')
->click('#balance-date')
->fill('#balance-date', '2024-02-01')
->click('button[type="submit"]:has-text("Save")')
->wait(2)
->click('button[aria-label="More options"]')
->wait(0.5)
->click('See balances')
->wait(2)
->assertSee('Balance History')
->assertSee('Feb 1, 2024')
->assertSee('Jan 1, 2024')
->assertNoJavascriptErrors();
$this->assertDatabaseHas('account_balances', [
'account_id' => $account->id,
'balance_date' => '2024-02-01',
'balance' => 12000000,
]);
});
it('can link and unlink a loan from the real estate details page', function () {
$user = User::factory()->onboarded()->create();
$bank = Bank::factory()->create(['name' => 'Property Bank', 'logo' => null]);
$loanBank = Bank::factory()->create(['name' => 'Mortgage Bank', 'logo' => null]);
$property = Account::factory()->create([
'user_id' => $user->id,
'bank_id' => null,
'name' => 'Beach Condo',
'type' => AccountType::RealEstate,
'currency_code' => 'EUR',
]);
AccountBalance::factory()->create([
'account_id' => $property->id,
'balance_date' => '2024-01-01',
'balance' => 30000000,
]);
RealEstateDetail::factory()->create([
'account_id' => $property->id,
'property_type' => 'residential',
'address' => 'Ocean Avenue 1',
'linked_loan_account_id' => null,
]);
$loan = Account::factory()->create([
'user_id' => $user->id,
'bank_id' => $loanBank->id,
'name' => 'Beach Mortgage',
'type' => AccountType::Loan,
'currency_code' => 'EUR',
]);
LoanDetail::factory()->create([
'account_id' => $loan->id,
'annual_interest_rate' => 3.1,
'loan_term_months' => 300,
'original_amount' => 22000000,
'start_date' => '2024-01-01',
]);
AccountBalance::factory()->create([
'account_id' => $loan->id,
'balance_date' => '2024-01-01',
'balance' => 20000000,
]);
actingAs($user);
$page = visit('/accounts');
$page->navigate('/accounts', ['waitUntil' => 'domcontentloaded'])->wait(2);
$page->waitForText('Beach Condo')
->click('Details →')
->wait(2)
->assertSee('Property Details')
->assertDontSee('Linked Mortgage / Loan')
->click('Edit')
->wait(1)
->assertSee('Edit Property Details')
->click('xpath=//label[contains(., "Linked Mortgage / Loan")]/following::button[@role="combobox"][1]')
->wait(0.5)
->click('[role="option"]:has-text("Beach Mortgage")')
->wait(0.5)
->click('button[type="submit"]:has-text("Save")')
->wait(2)
->assertSee('Linked Mortgage / Loan')
->assertSee('Beach Mortgage (Mortgage Bank)')
->click('Edit')
->wait(1)
->click('xpath=//label[contains(., "Linked Mortgage / Loan")]/following::button[@role="combobox"][1]')
->wait(0.5)
->click('[role="option"]:has-text("No linked loan")')
->wait(0.5)
->click('button[type="submit"]:has-text("Save")')
->wait(2)
->assertDontSee('Beach Mortgage (Mortgage Bank)')
->assertNoJavascriptErrors();
$detail = RealEstateDetail::query()->where('account_id', $property->id)->first();
expect($detail)->not->toBeNull();
expect($detail->fresh()->linked_loan_account_id)->toBeNull();
});
it('does not show other users accounts', function () {
$user = User::factory()->onboarded()->create();
$otherUser = User::factory()->onboarded()->create();

View File

@ -1,8 +1,11 @@
<?php
use App\Enums\AccountType;
use App\Models\Account;
use App\Models\Bank;
use App\Models\RealEstateDetail;
use App\Models\User;
use Laravel\Pennant\Feature;
use function Pest\Laravel\actingAs;
@ -92,6 +95,127 @@ it('can create a new bank account', function () {
]);
});
it('can create a loan account with balance and loan details', function () {
$user = User::factory()->onboarded()->create();
$bank = Bank::factory()->create(['name' => 'Mortgage Bank', 'logo' => null]);
actingAs($user);
$page = visit('/settings/accounts');
$page->assertSee('Bank accounts')
->click('Create Account')
->wait(0.5)
->fill('#display_name', 'Home Mortgage')
->click('[data-testid="bank-select"]')
->wait(0.5)
->fill('input[placeholder="Search bank..."]', 'Mortgage Bank')
->wait(0.5)
->click('Mortgage Bank')
->click('button[name="type"]')
->wait(0.5)
->click('[role="option"]:has-text("Loan")')
->wait(0.3)
->click('button[name="currency_code"]')
->wait(0.5)
->click('[role="option"]:has-text("EUR")')
->wait(0.3)
->fill('#balance', '180000')
->fill('#annual_interest_rate', '3.5')
->fill('#loan_term_months', '360')
->fill('#loan_start_date', '2024-01-01')
->fill('#original_amount', '250000')
->click('[data-testid="submit-account"]')
->wait(2)
->assertNoJavascriptErrors();
$loan = Account::query()
->where('user_id', $user->id)
->where('type', AccountType::Loan)
->first();
expect($loan)->not->toBeNull();
expect($loan->currency_code)->toBe('EUR');
expect($loan->balances)->toHaveCount(1);
expect($loan->balances->first()->balance)->toBe(18000000);
expect($loan->loanDetail)->not->toBeNull();
expect($loan->loanDetail->loan_term_months)->toBe(360);
expect((string) $loan->loanDetail->annual_interest_rate)->toBe('3.500');
expect($loan->loanDetail->original_amount)->toBe(25000000);
});
it('can create a real estate account linked to an existing loan', function () {
$user = User::factory()->onboarded()->create();
Feature::for($user)->activate('real-estate');
$loanBank = Bank::factory()->create(['name' => 'Linked Mortgage Bank', 'logo' => null]);
$loanAccount = Account::factory()->create([
'user_id' => $user->id,
'bank_id' => $loanBank->id,
'name' => 'Primary Mortgage',
'type' => AccountType::Loan,
'currency_code' => 'EUR',
]);
actingAs($user);
$page = visit('/settings/accounts');
$page->assertSee('Bank accounts')
->click('Create Account')
->wait(0.5)
->fill('#display_name', 'City Apartment')
->click('button[name="type"]')
->wait(0.5)
->click('[role="option"]:has-text("Real Estate")')
->wait(0.3)
->click('button[name="currency_code"]')
->wait(0.5)
->click('[role="option"]:has-text("EUR")')
->wait(0.3)
->fill('#balance', '320000')
->click('button[name="property_type"]')
->wait(0.5)
->click('[role="option"]:has-text("Residential")')
->wait(0.3)
->fill('#address', '123 Linked Street')
->fill('#purchase_price', '275000')
->fill('#purchase_date', '2024-02-01')
->fill('#area_value', '82')
->click('button[name="area_unit"]')
->wait(0.5)
->click('[role="option"]:has-text("m²")')
->wait(0.3)
->click('button[name="linked_loan_account_id"]')
->wait(0.5)
->click('[role="option"]:has-text("Primary Mortgage")')
->wait(0.3)
->fill('#notes', 'Main residence')
->fill('#revaluation_percentage', '2.5')
->click('[data-testid="submit-account"]')
->wait(2)
->assertNoJavascriptErrors();
$account = Account::query()
->where('user_id', $user->id)
->where('type', AccountType::RealEstate)
->first();
expect($account)->not->toBeNull();
expect($account->balances)->toHaveCount(1);
expect($account->balances->first()->balance)->toBe(32000000);
$detail = RealEstateDetail::query()
->where('account_id', $account->id)
->first();
expect($detail)->not->toBeNull();
expect($detail->linked_loan_account_id)->toBe($loanAccount->id);
expect($detail->address)->toBe('123 Linked Street');
});
it('shows empty state when no accounts exist', function () {
$user = User::factory()->onboarded()->create();