diff --git a/tests/Browser/AccountsPageTest.php b/tests/Browser/AccountsPageTest.php index 7f7d411b..c7891876 100644 --- a/tests/Browser/AccountsPageTest.php +++ b/tests/Browser/AccountsPageTest.php @@ -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(); diff --git a/tests/Browser/BankAccountsTest.php b/tests/Browser/BankAccountsTest.php index b04324a0..d90da3e5 100644 --- a/tests/Browser/BankAccountsTest.php +++ b/tests/Browser/BankAccountsTest.php @@ -1,8 +1,11 @@ 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();