test: expand browser coverage for account types and transactions (#279)

## Summary
- add browser coverage for manual credit card, investment, retirement,
and other account creation flows
- replace placeholder transaction search coverage with real filter
assertions and add edit/delete transaction browser tests
- keep the new coverage focused on the existing account and transaction
browser test files

## Testing
- vendor/bin/pint --dirty --format agent
- php artisan test --compact tests/Browser/BankAccountsTest.php
tests/Browser/TransactionsTest.php
This commit is contained in:
Víctor Falcón 2026-04-13 13:02:21 +01:00 committed by GitHub
parent a7c1bd35ef
commit db359a0572
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 197 additions and 1 deletions

View File

@ -9,6 +9,35 @@ use Laravel\Pennant\Feature;
use function Pest\Laravel\actingAs;
function createManualAccountTypeViaUi($page, string $displayName, string $bankName, string $type, string $currency = 'EUR', ?string $balance = null): void
{
$page->assertSee('Bank accounts')
->click('Create Account')
->wait(0.5)
->fill('#display_name', $displayName)
->click('[data-testid="bank-select"]')
->wait(0.5)
->fill('input[placeholder="Search bank..."]', $bankName)
->wait(0.5)
->click($bankName)
->click('button[name="type"]')
->wait(0.5)
->click("[role=\"option\"]:has-text(\"{$type}\")")
->wait(0.3)
->click('button[name="currency_code"]')
->wait(0.5)
->click("[role=\"option\"]:has-text(\"{$currency}\")")
->wait(0.3);
if ($balance !== null) {
$page->fill('#balance', $balance);
}
$page->click('[data-testid="submit-account"]')
->wait(2)
->assertNoJavascriptErrors();
}
it('can view bank accounts page', function () {
$user = User::factory()->onboarded()->create();
@ -144,6 +173,43 @@ it('can create a loan account with balance and loan details', function () {
expect($loan->loanDetail->original_amount)->toBe(25000000);
});
it('can create the remaining manual account types', function (string $typeLabel, AccountType $type, ?string $balance) {
$user = User::factory()->onboarded()->create();
$bank = Bank::factory()->create(['name' => 'Coverage Bank', 'logo' => null]);
actingAs($user);
$page = visit('/settings/accounts');
createManualAccountTypeViaUi(
$page,
"{$typeLabel} Coverage Account",
'Coverage Bank',
$typeLabel,
'EUR',
$balance,
);
$account = Account::query()
->where('user_id', $user->id)
->where('type', $type)
->first();
expect($account)->not->toBeNull();
expect($account->currency_code)->toBe('EUR');
if ($balance === null) {
expect($account->balances)->toHaveCount(0);
} else {
expect($account->balances)->toHaveCount(1);
}
})->with([
'credit card' => ['Credit Card', AccountType::CreditCard, null],
'investment' => ['Investment', AccountType::Investment, '125000'],
'retirement' => ['Retirement / Pension', AccountType::Retirement, '250000'],
'others' => ['Others', AccountType::Others, null],
]);
it('can create a real estate account linked to an existing loan', function () {
$user = User::factory()->onboarded()->create();

View File

@ -3,6 +3,7 @@
use App\Models\Account;
use App\Models\Bank;
use App\Models\Category;
use App\Models\Transaction;
use App\Models\User;
use function Pest\Laravel\actingAs;
@ -101,12 +102,141 @@ it('shows empty state when no transactions exist', function () {
it('can filter transactions by search text', function () {
$user = User::factory()->onboarded()->create();
$bank = Bank::factory()->create(['name' => 'Filter Bank']);
$category = Category::factory()->create([
'user_id' => $user->id,
'name' => 'Groceries',
]);
$account = Account::factory()->create([
'user_id' => $user->id,
'bank_id' => $bank->id,
'name' => 'Daily Account',
'currency_code' => 'USD',
'type' => 'checking',
]);
Transaction::factory()->plaintext()->create([
'user_id' => $user->id,
'account_id' => $account->id,
'category_id' => $category->id,
'description' => 'Weekly groceries',
'amount' => -4500,
]);
Transaction::factory()->plaintext()->create([
'user_id' => $user->id,
'account_id' => $account->id,
'category_id' => $category->id,
'description' => 'Electric bill',
'amount' => -8000,
]);
actingAs($user);
$page = visit('/transactions');
$page->assertSee('Transactions')
->wait(2)
->waitForText('Weekly groceries', 10)
->assertSee('Electric bill')
->fill('input[placeholder="Search description or notes..."]', 'groceries')
->wait(1)
->assertSee('Weekly groceries')
->assertDontSee('Electric bill')
->assertNoJavascriptErrors();
});
it('can edit an existing transaction from the list', function () {
$user = User::factory()->onboarded()->create();
$bank = Bank::factory()->create(['name' => 'Edit Tx Bank']);
$category = Category::factory()->create([
'user_id' => $user->id,
'name' => 'Groceries',
]);
$replacementCategory = Category::factory()->create([
'user_id' => $user->id,
'name' => 'Dining Out',
]);
$account = Account::factory()->create([
'user_id' => $user->id,
'bank_id' => $bank->id,
'name' => 'Editing Account',
'currency_code' => 'USD',
'type' => 'checking',
]);
$transaction = Transaction::factory()->plaintext()->create([
'user_id' => $user->id,
'account_id' => $account->id,
'category_id' => $category->id,
'description' => 'Original transaction note',
'amount' => -3200,
'notes' => 'Original note',
'source' => 'manually_created',
]);
actingAs($user);
$page = visit('/transactions');
$page->assertSee('Transactions')
->waitForText('Original transaction note', 10)
->click('Original transaction note')
->wait(1)
->assertSee('Edit Transaction')
->fill('#description', 'Updated dinner transaction')
->click('[data-testid="category-select"]')
->wait(1)
->click('Dining Out')
->fill('#notes', 'Updated note for browser test')
->click('[data-testid="submit-transaction"]')
->wait(3)
->waitForText('Updated dinner transaction', 10)
->assertSee('Dining Out')
->assertNoJavascriptErrors();
$updatedTransaction = $transaction->fresh();
expect($updatedTransaction->description)->toBe('Updated dinner transaction');
expect($updatedTransaction->notes)->toBe('Updated note for browser test');
expect($updatedTransaction->category_id)->toBe($replacementCategory->id);
});
it('can delete a transaction from the actions menu', function () {
$user = User::factory()->onboarded()->create();
$bank = Bank::factory()->create(['name' => 'Delete Tx Bank']);
$category = Category::factory()->create([
'user_id' => $user->id,
'name' => 'Household',
]);
$account = Account::factory()->create([
'user_id' => $user->id,
'bank_id' => $bank->id,
'name' => 'Delete Account',
'currency_code' => 'USD',
'type' => 'checking',
]);
$transaction = Transaction::factory()->plaintext()->create([
'user_id' => $user->id,
'account_id' => $account->id,
'category_id' => $category->id,
'description' => 'Disposable transaction',
'amount' => -1500,
]);
actingAs($user);
$page = visit('/transactions');
$page->assertSee('Transactions')
->waitForText('Disposable transaction', 10)
->click('button:has-text("Open menu")')
->wait(0.5)
->click('Delete')
->wait(0.5)
->assertSee('Delete Transaction')
->click('button:has-text("Delete")')
->wait(3)
->assertDontSee('Disposable transaction')
->assertNoJavascriptErrors();
});