Fix improve testing
This commit is contained in:
parent
5cfe3c81a1
commit
981df8cd68
|
|
@ -29,9 +29,9 @@ class ResetUserCategories extends Command
|
|||
{
|
||||
$userIdentifier = $this->argument('user');
|
||||
|
||||
$user = is_numeric($userIdentifier)
|
||||
? User::find($userIdentifier)
|
||||
: User::where('email', $userIdentifier)->first();
|
||||
$user = filter_var($userIdentifier, FILTER_VALIDATE_EMAIL)
|
||||
? User::where('email', $userIdentifier)->first()
|
||||
: User::find($userIdentifier);
|
||||
|
||||
if (! $user) {
|
||||
$this->error("User not found: {$userIdentifier}");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
|
||||
use App\Models\User;
|
||||
|
||||
it('can register a new user', function () {
|
||||
$page = visit('/register');
|
||||
|
||||
$page->assertSee('Create an account')
|
||||
->fill('name', 'Test User')
|
||||
->fill('email', 'newuser@example.com')
|
||||
->fill('password', 'password123')
|
||||
->fill('password_confirmation', 'password123')
|
||||
->click('@register-user-button')
|
||||
->waitFor('Setup your encryption')
|
||||
->assertUrlIs('/setup-encryption')
|
||||
->assertNoJavascriptErrors();
|
||||
|
||||
$this->assertDatabaseHas('users', [
|
||||
'email' => 'newuser@example.com',
|
||||
'name' => 'Test User',
|
||||
]);
|
||||
});
|
||||
|
||||
it('shows validation errors for invalid registration', function () {
|
||||
$page = visit('/register');
|
||||
|
||||
$page->assertSee('Create an account')
|
||||
->fill('name', 'Test User')
|
||||
->fill('email', 'invalid-email')
|
||||
->fill('password', 'short')
|
||||
->fill('password_confirmation', 'different')
|
||||
->click('@register-user-button')
|
||||
->wait(1)
|
||||
->assertNoJavascriptErrors();
|
||||
});
|
||||
|
||||
it('can login with valid credentials', function () {
|
||||
$user = User::factory()->create([
|
||||
'email' => 'test@example.com',
|
||||
'password' => bcrypt('password123'),
|
||||
'encryption_salt' => str_repeat('a', 24),
|
||||
]);
|
||||
|
||||
$page = visit('/login');
|
||||
|
||||
$page->assertSee('Log in to your account')
|
||||
->fill('email', 'test@example.com')
|
||||
->fill('password', 'password123')
|
||||
->click('@login-button')
|
||||
->waitFor('Dashboard')
|
||||
->assertUrlIs('/dashboard')
|
||||
->assertNoJavascriptErrors();
|
||||
|
||||
$this->assertAuthenticated();
|
||||
});
|
||||
|
||||
it('shows validation error for invalid login credentials', function () {
|
||||
$user = User::factory()->create([
|
||||
'email' => 'test@example.com',
|
||||
'password' => bcrypt('password123'),
|
||||
]);
|
||||
|
||||
$page = visit('/login');
|
||||
|
||||
$page->assertSee('Log in to your account')
|
||||
->fill('email', 'test@example.com')
|
||||
->fill('password', 'wrongpassword')
|
||||
->click('@login-button')
|
||||
->wait(1)
|
||||
->assertSee('These credentials do not match our records')
|
||||
->assertNoJavascriptErrors();
|
||||
});
|
||||
|
||||
it('can navigate from login to register', function () {
|
||||
$page = visit('/login');
|
||||
|
||||
$page->assertSee('Log in to your account')
|
||||
->click('Sign up')
|
||||
->waitFor('Create an account')
|
||||
->assertUrlIs('/register')
|
||||
->assertNoJavascriptErrors();
|
||||
});
|
||||
|
||||
it('can navigate from register to login', function () {
|
||||
$page = visit('/register');
|
||||
|
||||
$page->assertSee('Create an account')
|
||||
->click('Log in')
|
||||
->waitFor('Log in to your account')
|
||||
->assertUrlIs('/login')
|
||||
->assertNoJavascriptErrors();
|
||||
});
|
||||
|
|
@ -0,0 +1,186 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Account;
|
||||
use App\Models\Bank;
|
||||
use App\Models\User;
|
||||
|
||||
use function Pest\Laravel\actingAs;
|
||||
|
||||
it('can view bank accounts page', function () {
|
||||
$user = User::factory()->create(['encryption_salt' => str_repeat('a', 24)]);
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$page = visit('/settings/accounts');
|
||||
|
||||
$page->assertSee('Bank accounts')
|
||||
->assertSee('Manage your bank accounts')
|
||||
->assertNoJavascriptErrors();
|
||||
});
|
||||
|
||||
it('shows existing accounts in list', function () {
|
||||
$user = User::factory()->create(['encryption_salt' => str_repeat('a', 24)]);
|
||||
$bank = Bank::factory()->create(['name' => 'Test Bank']);
|
||||
Account::factory()->create([
|
||||
'user_id' => $user->id,
|
||||
'bank_id' => $bank->id,
|
||||
'name' => 'My Checking',
|
||||
'name_iv' => str_repeat('b', 16),
|
||||
'type' => 'checking',
|
||||
'currency_code' => 'USD',
|
||||
]);
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$page = visit('/settings/accounts');
|
||||
|
||||
$page->assertSee('Bank accounts')
|
||||
->assertSee('Test Bank')
|
||||
->assertSee('Checking')
|
||||
->assertSee('USD')
|
||||
->assertNoJavascriptErrors();
|
||||
});
|
||||
|
||||
it('can open create account dialog', function () {
|
||||
$user = User::factory()->create(['encryption_salt' => str_repeat('a', 24)]);
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$page = visit('/settings/accounts');
|
||||
|
||||
$page->assertSee('Bank accounts')
|
||||
->click('Create Account')
|
||||
->waitFor('dialog')
|
||||
->assertSee('Add a new bank account to track your transactions')
|
||||
->assertNoJavascriptErrors();
|
||||
});
|
||||
|
||||
it('can create a new bank account', function () {
|
||||
$user = User::factory()->create(['encryption_salt' => str_repeat('a', 24)]);
|
||||
$bank = Bank::factory()->create(['name' => 'My Bank']);
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$page = visit('/settings/accounts');
|
||||
|
||||
$page->assertSee('Bank accounts')
|
||||
->click('Create Account')
|
||||
->waitFor('dialog')
|
||||
->fill('#display_name', 'My Savings Account')
|
||||
->click('Select a bank...')
|
||||
->wait(0.5)
|
||||
->fill('input[placeholder="Search banks..."]', 'My Bank')
|
||||
->wait(0.5)
|
||||
->click('My Bank')
|
||||
->click('Select account type')
|
||||
->wait(0.3)
|
||||
->click('Savings')
|
||||
->click('Select currency')
|
||||
->wait(0.3)
|
||||
->click('EUR')
|
||||
->click('button[type="submit"]')
|
||||
->wait(2)
|
||||
->assertNoJavascriptErrors();
|
||||
|
||||
$this->assertDatabaseHas('accounts', [
|
||||
'user_id' => $user->id,
|
||||
'bank_id' => $bank->id,
|
||||
'type' => 'savings',
|
||||
'currency_code' => 'EUR',
|
||||
]);
|
||||
});
|
||||
|
||||
it('shows empty state when no accounts exist', function () {
|
||||
$user = User::factory()->create(['encryption_salt' => str_repeat('a', 24)]);
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$page = visit('/settings/accounts');
|
||||
|
||||
$page->assertSee('Bank accounts')
|
||||
->assertSee('No accounts found')
|
||||
->assertNoJavascriptErrors();
|
||||
});
|
||||
|
||||
it('can filter accounts by name', function () {
|
||||
$user = User::factory()->create(['encryption_salt' => str_repeat('a', 24)]);
|
||||
$bank = Bank::factory()->create(['name' => 'Test Bank']);
|
||||
Account::factory()->create([
|
||||
'user_id' => $user->id,
|
||||
'bank_id' => $bank->id,
|
||||
'name' => 'Checking Account',
|
||||
'name_iv' => str_repeat('b', 16),
|
||||
]);
|
||||
Account::factory()->create([
|
||||
'user_id' => $user->id,
|
||||
'bank_id' => $bank->id,
|
||||
'name' => 'Savings Account',
|
||||
'name_iv' => str_repeat('c', 16),
|
||||
]);
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$page = visit('/settings/accounts');
|
||||
|
||||
$page->assertSee('Bank accounts')
|
||||
->fill('input[placeholder="Filter accounts..."]', 'Checking')
|
||||
->wait(0.5)
|
||||
->assertNoJavascriptErrors();
|
||||
});
|
||||
|
||||
it('can edit an existing account via dropdown menu', function () {
|
||||
$user = User::factory()->create(['encryption_salt' => str_repeat('a', 24)]);
|
||||
$bank = Bank::factory()->create(['name' => 'Test Bank']);
|
||||
$account = Account::factory()->create([
|
||||
'user_id' => $user->id,
|
||||
'bank_id' => $bank->id,
|
||||
'name' => 'Old Account Name',
|
||||
'name_iv' => str_repeat('b', 16),
|
||||
'type' => 'checking',
|
||||
'currency_code' => 'USD',
|
||||
]);
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$page = visit('/settings/accounts');
|
||||
|
||||
$page->assertSee('Bank accounts')
|
||||
->click('button[aria-label="Open menu"]')
|
||||
->wait(0.3)
|
||||
->click('Edit')
|
||||
->waitFor('dialog')
|
||||
->assertSee('Edit Account')
|
||||
->fill('#display_name', 'Updated Account Name')
|
||||
->click('Save')
|
||||
->wait(2)
|
||||
->assertNoJavascriptErrors();
|
||||
});
|
||||
|
||||
it('can delete an account via dropdown menu', function () {
|
||||
$user = User::factory()->create(['encryption_salt' => str_repeat('a', 24)]);
|
||||
$bank = Bank::factory()->create(['name' => 'Test Bank']);
|
||||
$account = Account::factory()->create([
|
||||
'user_id' => $user->id,
|
||||
'bank_id' => $bank->id,
|
||||
'name' => 'Account To Delete',
|
||||
'name_iv' => str_repeat('b', 16),
|
||||
]);
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$page = visit('/settings/accounts');
|
||||
|
||||
$page->assertSee('Bank accounts')
|
||||
->click('button[aria-label="Open menu"]')
|
||||
->wait(0.3)
|
||||
->click('Delete')
|
||||
->waitFor('dialog')
|
||||
->assertSee('Delete Account')
|
||||
->click('Delete')
|
||||
->wait(2)
|
||||
->assertNoJavascriptErrors();
|
||||
|
||||
$this->assertDatabaseMissing('accounts', [
|
||||
'id' => $account->id,
|
||||
]);
|
||||
});
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Category;
|
||||
use App\Models\User;
|
||||
|
||||
use function Pest\Laravel\actingAs;
|
||||
|
||||
it('can view categories page', function () {
|
||||
$user = User::factory()->create(['encryption_salt' => str_repeat('a', 24)]);
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$page = visit('/settings/categories');
|
||||
|
||||
$page->assertSee('Categories settings')
|
||||
->assertSee('Manage your transaction categories')
|
||||
->assertNoJavascriptErrors();
|
||||
});
|
||||
|
||||
it('shows existing categories in list', function () {
|
||||
$user = User::factory()->create(['encryption_salt' => str_repeat('a', 24)]);
|
||||
$category = Category::factory()->create([
|
||||
'user_id' => $user->id,
|
||||
'name' => 'Groceries',
|
||||
'icon' => 'ShoppingCart',
|
||||
'color' => 'green',
|
||||
]);
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$page = visit('/settings/categories');
|
||||
|
||||
$page->assertSee('Categories settings')
|
||||
->assertSee('Groceries')
|
||||
->assertNoJavascriptErrors();
|
||||
});
|
||||
|
||||
it('can open create category dialog', function () {
|
||||
$user = User::factory()->create(['encryption_salt' => str_repeat('a', 24)]);
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$page = visit('/settings/categories');
|
||||
|
||||
$page->assertSee('Categories settings')
|
||||
->click('Create Category')
|
||||
->waitFor('dialog')
|
||||
->assertSee('Add a new category to organize your transactions')
|
||||
->assertNoJavascriptErrors();
|
||||
});
|
||||
|
||||
it('can create a new category', function () {
|
||||
$user = User::factory()->create(['encryption_salt' => str_repeat('a', 24)]);
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$page = visit('/settings/categories');
|
||||
|
||||
$page->assertSee('Categories settings')
|
||||
->click('Create Category')
|
||||
->waitFor('dialog')
|
||||
->fill('name', 'Entertainment')
|
||||
->click('Select an icon')
|
||||
->wait(0.3)
|
||||
->click('Film')
|
||||
->click('Select a color')
|
||||
->wait(0.3)
|
||||
->click('purple')
|
||||
->click('button[type="submit"]')
|
||||
->wait(2)
|
||||
->assertSee('Entertainment')
|
||||
->assertNoJavascriptErrors();
|
||||
|
||||
$this->assertDatabaseHas('categories', [
|
||||
'user_id' => $user->id,
|
||||
'name' => 'Entertainment',
|
||||
'icon' => 'Film',
|
||||
'color' => 'purple',
|
||||
]);
|
||||
});
|
||||
|
||||
it('can filter categories by name', function () {
|
||||
$user = User::factory()->create(['encryption_salt' => str_repeat('a', 24)]);
|
||||
Category::factory()->create([
|
||||
'user_id' => $user->id,
|
||||
'name' => 'Groceries',
|
||||
]);
|
||||
Category::factory()->create([
|
||||
'user_id' => $user->id,
|
||||
'name' => 'Entertainment',
|
||||
]);
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$page = visit('/settings/categories');
|
||||
|
||||
$page->assertSee('Categories settings')
|
||||
->fill('input[placeholder="Filter categories..."]', 'Groceries')
|
||||
->wait(0.5)
|
||||
->assertSee('Groceries')
|
||||
->assertNoJavascriptErrors();
|
||||
});
|
||||
|
||||
it('shows empty state when no categories exist', function () {
|
||||
$user = User::factory()->create(['encryption_salt' => str_repeat('a', 24)]);
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$page = visit('/settings/categories');
|
||||
|
||||
$page->assertSee('Categories settings')
|
||||
->assertSee('No categories found')
|
||||
->assertNoJavascriptErrors();
|
||||
});
|
||||
|
||||
it('can edit an existing category via context menu', function () {
|
||||
$user = User::factory()->create(['encryption_salt' => str_repeat('a', 24)]);
|
||||
$category = Category::factory()->create([
|
||||
'user_id' => $user->id,
|
||||
'name' => 'Old Category',
|
||||
'icon' => 'Tag',
|
||||
'color' => 'blue',
|
||||
]);
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$page = visit('/settings/categories');
|
||||
|
||||
$page->assertSee('Old Category')
|
||||
->click('button[aria-label="Open menu"]')
|
||||
->wait(0.3)
|
||||
->click('Edit')
|
||||
->waitFor('dialog')
|
||||
->assertSee('Edit Category')
|
||||
->fill('name', 'Updated Category')
|
||||
->click('Save')
|
||||
->wait(2)
|
||||
->assertSee('Updated Category')
|
||||
->assertNoJavascriptErrors();
|
||||
|
||||
$this->assertDatabaseHas('categories', [
|
||||
'id' => $category->id,
|
||||
'name' => 'Updated Category',
|
||||
]);
|
||||
});
|
||||
|
|
@ -0,0 +1,233 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Account;
|
||||
use App\Models\Bank;
|
||||
use App\Models\Category;
|
||||
use App\Models\User;
|
||||
|
||||
use function Pest\Laravel\actingAs;
|
||||
|
||||
it('can open import transactions drawer', function () {
|
||||
$user = User::factory()->create(['encryption_salt' => str_repeat('a', 24)]);
|
||||
Category::factory()->create(['user_id' => $user->id]);
|
||||
$bank = Bank::factory()->create(['name' => 'Test Bank']);
|
||||
Account::factory()->create([
|
||||
'user_id' => $user->id,
|
||||
'bank_id' => $bank->id,
|
||||
'name' => 'Test Account',
|
||||
'name_iv' => str_repeat('b', 16),
|
||||
]);
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$page = visit('/transactions');
|
||||
|
||||
$page->assertSee('Transactions')
|
||||
->click('button[aria-label="More actions"]')
|
||||
->wait(0.3)
|
||||
->click('Import Transactions')
|
||||
->waitFor('drawer')
|
||||
->assertSee('Import Transactions')
|
||||
->assertSee('Select the account to import transactions into')
|
||||
->assertNoJavascriptErrors();
|
||||
});
|
||||
|
||||
it('shows no accounts message when none exist', function () {
|
||||
$user = User::factory()->create(['encryption_salt' => str_repeat('a', 24)]);
|
||||
Category::factory()->create(['user_id' => $user->id]);
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$page = visit('/transactions');
|
||||
|
||||
$page->assertSee('Transactions')
|
||||
->click('button[aria-label="More actions"]')
|
||||
->wait(0.3)
|
||||
->click('Import Transactions')
|
||||
->waitFor('drawer')
|
||||
->assertSee('No accounts found')
|
||||
->assertNoJavascriptErrors();
|
||||
});
|
||||
|
||||
it('can select account for import', function () {
|
||||
$user = User::factory()->create(['encryption_salt' => str_repeat('a', 24)]);
|
||||
Category::factory()->create(['user_id' => $user->id]);
|
||||
$bank = Bank::factory()->create(['name' => 'My Bank']);
|
||||
Account::factory()->create([
|
||||
'user_id' => $user->id,
|
||||
'bank_id' => $bank->id,
|
||||
'name' => 'My Checking',
|
||||
'name_iv' => str_repeat('b', 16),
|
||||
'currency_code' => 'USD',
|
||||
]);
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$page = visit('/transactions');
|
||||
|
||||
$page->assertSee('Transactions')
|
||||
->click('button[aria-label="More actions"]')
|
||||
->wait(0.3)
|
||||
->click('Import Transactions')
|
||||
->waitFor('drawer')
|
||||
->assertSee('My Bank')
|
||||
->assertSee('USD')
|
||||
->click('label')
|
||||
->wait(0.3)
|
||||
->click('Next')
|
||||
->waitFor('Drop your file here')
|
||||
->assertSee('Supports CSV, XLS, and XLSX files')
|
||||
->assertNoJavascriptErrors();
|
||||
});
|
||||
|
||||
it('can upload a CSV file for import', function () {
|
||||
$user = User::factory()->create(['encryption_salt' => str_repeat('a', 24)]);
|
||||
Category::factory()->create(['user_id' => $user->id]);
|
||||
$bank = Bank::factory()->create(['name' => 'My Bank']);
|
||||
Account::factory()->create([
|
||||
'user_id' => $user->id,
|
||||
'bank_id' => $bank->id,
|
||||
'name' => 'My Checking',
|
||||
'name_iv' => str_repeat('b', 16),
|
||||
'currency_code' => 'USD',
|
||||
]);
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$page = visit('/transactions');
|
||||
|
||||
$testFile = __DIR__.'/assets/test-transactions.csv';
|
||||
|
||||
$page->assertSee('Transactions')
|
||||
->click('button[aria-label="More actions"]')
|
||||
->wait(0.3)
|
||||
->click('Import Transactions')
|
||||
->waitFor('drawer')
|
||||
->click('label')
|
||||
->wait(0.3)
|
||||
->click('Next')
|
||||
->waitFor('Drop your file here')
|
||||
->attach('input[type="file"]', $testFile)
|
||||
->wait(1)
|
||||
->assertSee('test-transactions.csv')
|
||||
->assertNoJavascriptErrors();
|
||||
});
|
||||
|
||||
it('can complete full import flow', function () {
|
||||
$user = User::factory()->create(['encryption_salt' => str_repeat('a', 24)]);
|
||||
Category::factory()->create(['user_id' => $user->id]);
|
||||
$bank = Bank::factory()->create(['name' => 'My Bank']);
|
||||
$account = Account::factory()->create([
|
||||
'user_id' => $user->id,
|
||||
'bank_id' => $bank->id,
|
||||
'name' => 'My Checking',
|
||||
'name_iv' => str_repeat('b', 16),
|
||||
'currency_code' => 'USD',
|
||||
]);
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$page = visit('/transactions');
|
||||
|
||||
$testFile = __DIR__.'/assets/test-transactions.csv';
|
||||
|
||||
$page->assertSee('Transactions')
|
||||
->click('button[aria-label="More actions"]')
|
||||
->wait(0.3)
|
||||
->click('Import Transactions')
|
||||
->waitFor('drawer')
|
||||
->click('label')
|
||||
->wait(0.5)
|
||||
->click('Next')
|
||||
->waitFor('Drop your file here')
|
||||
->attach('input[type="file"]', $testFile)
|
||||
->wait(1)
|
||||
->assertSee('test-transactions.csv')
|
||||
->click('Next')
|
||||
->wait(1)
|
||||
->waitFor('Transaction Date')
|
||||
->click('#date-column')
|
||||
->wait(0.3)
|
||||
->click('Date')
|
||||
->click('#description-column')
|
||||
->wait(0.3)
|
||||
->click('Description')
|
||||
->click('#amount-column')
|
||||
->wait(0.3)
|
||||
->click('Amount')
|
||||
->wait(0.5)
|
||||
->click('Preview Transactions')
|
||||
->wait(2)
|
||||
->assertSee('Total')
|
||||
->assertSee('New')
|
||||
->assertNoJavascriptErrors();
|
||||
});
|
||||
|
||||
it('shows column mapping step after file upload', function () {
|
||||
$user = User::factory()->create(['encryption_salt' => str_repeat('a', 24)]);
|
||||
Category::factory()->create(['user_id' => $user->id]);
|
||||
$bank = Bank::factory()->create(['name' => 'My Bank']);
|
||||
Account::factory()->create([
|
||||
'user_id' => $user->id,
|
||||
'bank_id' => $bank->id,
|
||||
'name' => 'My Checking',
|
||||
'name_iv' => str_repeat('b', 16),
|
||||
'currency_code' => 'USD',
|
||||
]);
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$page = visit('/transactions');
|
||||
|
||||
$testFile = __DIR__.'/assets/test-transactions.csv';
|
||||
|
||||
$page->assertSee('Transactions')
|
||||
->click('button[aria-label="More actions"]')
|
||||
->wait(0.3)
|
||||
->click('Import Transactions')
|
||||
->waitFor('drawer')
|
||||
->click('label')
|
||||
->wait(0.5)
|
||||
->click('Next')
|
||||
->waitFor('Drop your file here')
|
||||
->attach('input[type="file"]', $testFile)
|
||||
->wait(1)
|
||||
->click('Next')
|
||||
->wait(1)
|
||||
->assertSee('Transaction Date')
|
||||
->assertSee('Description')
|
||||
->assertSee('Amount')
|
||||
->assertSee('Balance (Optional)')
|
||||
->assertNoJavascriptErrors();
|
||||
});
|
||||
|
||||
it('can navigate back through import steps', function () {
|
||||
$user = User::factory()->create(['encryption_salt' => str_repeat('a', 24)]);
|
||||
Category::factory()->create(['user_id' => $user->id]);
|
||||
$bank = Bank::factory()->create(['name' => 'My Bank']);
|
||||
Account::factory()->create([
|
||||
'user_id' => $user->id,
|
||||
'bank_id' => $bank->id,
|
||||
'name' => 'My Checking',
|
||||
'name_iv' => str_repeat('b', 16),
|
||||
'currency_code' => 'USD',
|
||||
]);
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$page = visit('/transactions');
|
||||
|
||||
$page->assertSee('Transactions')
|
||||
->click('button[aria-label="More actions"]')
|
||||
->wait(0.3)
|
||||
->click('Import Transactions')
|
||||
->waitFor('drawer')
|
||||
->click('label')
|
||||
->wait(0.5)
|
||||
->click('Next')
|
||||
->waitFor('Drop your file here')
|
||||
->click('Back')
|
||||
->wait(0.5)
|
||||
->assertSee('Select the account to import transactions into')
|
||||
->assertNoJavascriptErrors();
|
||||
});
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Account;
|
||||
use App\Models\Category;
|
||||
use App\Models\User;
|
||||
|
||||
use function Pest\Laravel\actingAs;
|
||||
|
||||
it('can view transactions page', function () {
|
||||
$user = User::factory()->create(['encryption_salt' => str_repeat('a', 24)]);
|
||||
Category::factory()->create(['user_id' => $user->id]);
|
||||
Account::factory()->create(['user_id' => $user->id]);
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$page = visit('/transactions');
|
||||
|
||||
$page->assertSee('Transactions')
|
||||
->assertSee('View and manage your transactions')
|
||||
->assertNoJavascriptErrors();
|
||||
});
|
||||
|
||||
it('can open add transaction dialog', function () {
|
||||
$user = User::factory()->create(['encryption_salt' => str_repeat('a', 24)]);
|
||||
Category::factory()->create(['user_id' => $user->id]);
|
||||
Account::factory()->create(['user_id' => $user->id]);
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$page = visit('/transactions');
|
||||
|
||||
$page->assertSee('Transactions')
|
||||
->click('Add Transaction')
|
||||
->waitFor('dialog')
|
||||
->assertSee('Create Transaction')
|
||||
->assertNoJavascriptErrors();
|
||||
});
|
||||
|
||||
it('can create a transaction', function () {
|
||||
$user = User::factory()->create(['encryption_salt' => str_repeat('a', 24)]);
|
||||
$category = Category::factory()->create(['user_id' => $user->id]);
|
||||
$account = Account::factory()->create(['user_id' => $user->id]);
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$page = visit('/transactions');
|
||||
|
||||
$page->assertSee('Transactions')
|
||||
->click('Add Transaction')
|
||||
->waitFor('dialog')
|
||||
->fill('description', 'Test Transaction')
|
||||
->click('Select Account')
|
||||
->wait(0.5)
|
||||
->click($account->name)
|
||||
->click('Select Category')
|
||||
->wait(0.5)
|
||||
->click($category->name)
|
||||
->fill('#amount', '50.00')
|
||||
->click('Create')
|
||||
->wait(2)
|
||||
->assertNoJavascriptErrors();
|
||||
|
||||
$this->assertDatabaseHas('transactions', [
|
||||
'user_id' => $user->id,
|
||||
'amount' => 5000,
|
||||
]);
|
||||
});
|
||||
|
||||
it('shows empty state when no transactions exist', function () {
|
||||
$user = User::factory()->create(['encryption_salt' => str_repeat('a', 24)]);
|
||||
Category::factory()->create(['user_id' => $user->id]);
|
||||
Account::factory()->create(['user_id' => $user->id]);
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$page = visit('/transactions');
|
||||
|
||||
$page->assertSee('Transactions')
|
||||
->assertSee('No transactions found')
|
||||
->assertNoJavascriptErrors();
|
||||
});
|
||||
|
||||
it('can filter transactions by search text', function () {
|
||||
$user = User::factory()->create(['encryption_salt' => str_repeat('a', 24)]);
|
||||
Category::factory()->create(['user_id' => $user->id]);
|
||||
Account::factory()->create(['user_id' => $user->id]);
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$page = visit('/transactions');
|
||||
|
||||
$page->assertSee('Transactions')
|
||||
->fill('input[placeholder="Search transactions..."]', 'grocery')
|
||||
->wait(0.5)
|
||||
->assertNoJavascriptErrors();
|
||||
});
|
||||
Binary file not shown.
|
|
@ -0,0 +1,7 @@
|
|||
Date,Description,Amount
|
||||
2024-01-15,Grocery Store Purchase,-50.25
|
||||
2024-01-16,Coffee Shop,-5.50
|
||||
2024-01-17,Salary Deposit,2500.00
|
||||
2024-01-18,Electric Bill,-125.00
|
||||
2024-01-19,Restaurant Dinner,-45.75
|
||||
|
||||
|
|
|
@ -12,11 +12,11 @@ test('command resets categories for a user by ID', function () {
|
|||
$this->artisan('categories:reset', ['user' => $user->id])
|
||||
->expectsOutput("Resetting categories for user: {$user->name} ({$user->email})")
|
||||
->expectsOutput('Deleted 5 existing categories.')
|
||||
->expectsOutput('Created 49 default categories.')
|
||||
->expectsOutput('Created 63 default categories.')
|
||||
->expectsOutput('✓ Categories reset successfully!')
|
||||
->assertSuccessful();
|
||||
|
||||
expect($user->fresh()->categories()->count())->toBe(49);
|
||||
expect($user->fresh()->categories()->count())->toBe(63);
|
||||
|
||||
$categoryNames = $user->categories->pluck('name')->toArray();
|
||||
expect($categoryNames)->toContain('Food', 'Transportation', 'Salary', 'Insurance');
|
||||
|
|
@ -31,11 +31,11 @@ test('command resets categories for a user by email', function () {
|
|||
$this->artisan('categories:reset', ['user' => 'test@example.com'])
|
||||
->expectsOutput("Resetting categories for user: {$user->name} (test@example.com)")
|
||||
->expectsOutput('Deleted 3 existing categories.')
|
||||
->expectsOutput('Created 49 default categories.')
|
||||
->expectsOutput('Created 63 default categories.')
|
||||
->expectsOutput('✓ Categories reset successfully!')
|
||||
->assertSuccessful();
|
||||
|
||||
expect($user->fresh()->categories()->count())->toBe(49);
|
||||
expect($user->fresh()->categories()->count())->toBe(63);
|
||||
});
|
||||
|
||||
test('command works when user has no existing categories', function () {
|
||||
|
|
@ -46,11 +46,11 @@ test('command works when user has no existing categories', function () {
|
|||
$this->artisan('categories:reset', ['user' => $user->id])
|
||||
->expectsOutput("Resetting categories for user: {$user->name} ({$user->email})")
|
||||
->expectsOutput('No existing categories found.')
|
||||
->expectsOutput('Created 49 default categories.')
|
||||
->expectsOutput('Created 63 default categories.')
|
||||
->expectsOutput('✓ Categories reset successfully!')
|
||||
->assertSuccessful();
|
||||
|
||||
expect($user->fresh()->categories()->count())->toBe(49);
|
||||
expect($user->fresh()->categories()->count())->toBe(63);
|
||||
});
|
||||
|
||||
test('command fails when user is not found by ID', function () {
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@ test('default categories are created when user registers', function () {
|
|||
$service = new \App\Actions\CreateDefaultCategories;
|
||||
$service->handle($user);
|
||||
|
||||
expect($user->categories()->count())->toBe(49);
|
||||
expect($user->categories()->count())->toBe(63);
|
||||
|
||||
$categoryNames = $user->categories->pluck('name')->toArray();
|
||||
expect($categoryNames)->toContain('Food', 'Transportation', 'Salary', 'Insurance');
|
||||
|
|
|
|||
Loading…
Reference in New Issue