diff --git a/app/Console/Commands/ResetUserCategories.php b/app/Console/Commands/ResetUserCategories.php index ac71fcf8..a564c077 100644 --- a/app/Console/Commands/ResetUserCategories.php +++ b/app/Console/Commands/ResetUserCategories.php @@ -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}"); diff --git a/tests/Browser/AuthenticationTest.php b/tests/Browser/AuthenticationTest.php new file mode 100644 index 00000000..3796c2a9 --- /dev/null +++ b/tests/Browser/AuthenticationTest.php @@ -0,0 +1,92 @@ +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(); +}); diff --git a/tests/Browser/BankAccountsTest.php b/tests/Browser/BankAccountsTest.php new file mode 100644 index 00000000..a676cab6 --- /dev/null +++ b/tests/Browser/BankAccountsTest.php @@ -0,0 +1,186 @@ +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, + ]); +}); diff --git a/tests/Browser/CategoriesTest.php b/tests/Browser/CategoriesTest.php new file mode 100644 index 00000000..b53766fb --- /dev/null +++ b/tests/Browser/CategoriesTest.php @@ -0,0 +1,145 @@ +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', + ]); +}); diff --git a/tests/Browser/ImportTransactionsTest.php b/tests/Browser/ImportTransactionsTest.php new file mode 100644 index 00000000..d6714ada --- /dev/null +++ b/tests/Browser/ImportTransactionsTest.php @@ -0,0 +1,233 @@ +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(); +}); diff --git a/tests/Browser/TransactionsTest.php b/tests/Browser/TransactionsTest.php new file mode 100644 index 00000000..f6139b38 --- /dev/null +++ b/tests/Browser/TransactionsTest.php @@ -0,0 +1,96 @@ +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(); +}); diff --git a/tests/Browser/assets/2025Y-11M-14D-11_59_09-Últimos movimientos.xlsx b/tests/Browser/assets/2025Y-11M-14D-11_59_09-Últimos movimientos.xlsx new file mode 100644 index 00000000..ef4a3c10 Binary files /dev/null and b/tests/Browser/assets/2025Y-11M-14D-11_59_09-Últimos movimientos.xlsx differ diff --git a/tests/Browser/assets/test-transactions.csv b/tests/Browser/assets/test-transactions.csv new file mode 100644 index 00000000..ac5daee7 --- /dev/null +++ b/tests/Browser/assets/test-transactions.csv @@ -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 + diff --git a/tests/Feature/Console/ResetUserCategoriesCommandTest.php b/tests/Feature/Console/ResetUserCategoriesCommandTest.php index 831f02cd..6d2fa003 100644 --- a/tests/Feature/Console/ResetUserCategoriesCommandTest.php +++ b/tests/Feature/Console/ResetUserCategoriesCommandTest.php @@ -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 () { diff --git a/tests/Feature/Settings/CategoryTest.php b/tests/Feature/Settings/CategoryTest.php index e8d24e74..c151d757 100644 --- a/tests/Feature/Settings/CategoryTest.php +++ b/tests/Feature/Settings/CategoryTest.php @@ -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');