Files
budget/scripts/onboarding-test.php
T
Ty Clifford 6686388834 - Implemented the complete first-run experience:
Account creation and guarded onboarding flow.
Current-cash starting balance with automatic rollover enabled.
Dynamic bill generation, shared/custom categories, recurring targets, 
and optional same-day onboarding transactions.
Optional dormant reserve and additional categories.
Mailgun email or authenticator-app 2FA configuration.
Responsive dark/light UI with no overflow at 390px.
Fixed administrator session-ID creation bug.
Core implementation: [OnboardingService.php (line 
59)](/Users/tyemeclifford/Documents/GH/budget/app/OnboardingService.php:59), 
[onboarding.php (line 
19)](/Users/tyemeclifford/Documents/GH/budget/views/onboarding.php:19), 
and [index.php (line 
143)](/Users/tyemeclifford/Documents/GH/budget/public/index.php:143).
Verification passed: financial self-test, onboarding integration test, 
full browser walkthrough, mobile layout, routing guards, and zero 
browser console errors. Live email delivery requires actual Mailgun 
credentials and was not sent during testing.
2026-06-15 14:51:44 -04:00

69 lines
2.7 KiB
PHP

<?php
declare(strict_types=1);
$databasePath = sys_get_temp_dir() . '/neon-ledger-onboarding-test-' . getmypid() . '.sqlite';
putenv('BUDGET_SQLITE_PATH=' . $databasePath);
register_shutdown_function(static function () use ($databasePath): void {
foreach ([$databasePath, $databasePath . '-shm', $databasePath . '-wal'] as $file) {
if (is_file($file)) {
unlink($file);
}
}
});
require __DIR__ . '/../app/bootstrap.php';
$assert = static function (bool $condition, string $message): void {
if (!$condition) {
throw new RuntimeException($message);
}
};
$month = date('Y-m');
$today = date('Y-m-d');
session_start();
$auth->setup('planner-test@example.com', 'TestingPlanner2026!', false);
$assert(($auth->user()['email'] ?? null) === 'planner-test@example.com', 'New account session did not retain the administrator ID.');
$settings->set('dead.transaction_mode', 'fixed');
$settings->set('dead.transaction_value', 1);
$settings->set('onboarding.completed', false);
$result = $onboarding->complete($month, 1000, [
[
'name' => 'Electric',
'amount' => 80,
'due_date' => $today,
'recurrence' => 'monthly',
'category' => 'Utilities',
'paid_now' => '1',
],
[
'name' => 'Internet',
'amount' => 55,
'due_date' => $today,
'recurrence' => 'monthly',
'category' => 'Utilities',
],
], ['Netflix', 'Luxury'], 100);
$summary = $budget->summary($month);
$items = $budget->budgetItems($month);
$transactions = $budget->transactions($month);
$categories = array_column($budget->categories(), 'name');
$assert((bool) $settings->get('onboarding.completed', false), 'Onboarding was not marked complete.');
$assert($result === ['bills' => 2, 'paid' => 1, 'categories' => 3, 'reserved' => 100.0], 'Onboarding result summary is incorrect.');
$assert(count($items) === 2, 'Bills were not converted into budget items.');
$assert(count($transactions) === 1, 'The paid bill did not create one transaction.');
$assert($transactions[0]['notes'] === 'onboarding', 'The onboarding transaction note is missing.');
$assert($transactions[0]['transacted_on'] === $today, 'The onboarding transaction date is incorrect.');
$assert(abs((float) $summary['remaining'] - 819) < 0.001, 'Onboarding remaining cash is incorrect.');
$assert(abs($budget->deadBalance() - 101) < 0.001, 'Dormant onboarding transfers are incorrect.');
$assert(in_array('Utilities', $categories, true), 'Consolidated Utilities category was not created.');
$assert(in_array('Netflix', $categories, true) && in_array('Luxury', $categories, true), 'Additional categories were not created.');
echo "Neon Ledger onboarding test passed.\n";