6686388834
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.
69 lines
2.7 KiB
PHP
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";
|