Bicycle/tests/Unit/BudgetRepositoryTest.php
Egor Isaev c9b81cdcd1 dev
2026-08-14 13:09:54 +03:00

160 lines
5.6 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace Tests\Unit;
use App\Repositories\BudgetRepository;
use PHPUnit\Framework\TestCase;
use ReflectionClass;
use Services\Database;
use Services\DataBase\Classes\PdoConnection;
use Services\DataBase\Classes\Profiler;
use System\Classes\Config;
use System\Classes\MyException;
use System\Classes\Repository;
/**
* BudgetRepository жёстко привязан к боевой таблице budgets конструктором, а getYear() делает
* JOIN к categories — для тестов подменяем обе таблицы на временные (тот же приём, что и в
* CategoryRepositoryTest: прямой вызов Repository::__construct(), минуя BudgetRepository::__construct()).
*/
class BudgetRepositoryTestDouble extends BudgetRepository
{
public function __construct(?string $connection = null)
{
Repository::__construct('budget_repository_test_budgets', connection: $connection);
$this->categories_table = 'budget_repository_test_categories';
}
}
class BudgetRepositoryTest extends TestCase
{
private PdoConnection $connection;
private BudgetRepositoryTestDouble $repository;
protected function setUp(): void
{
$config = Config::get('db', 'default') ?? [];
$this->connection = new PdoConnection($config);
try {
$this->connection->pdo();
} catch (MyException $e) {
$this->markTestSkipped('Нет живого подключения к MariaDB (заполните App/config/config.local.php): ' . $e->getMessage());
}
$this->connection->exec('DROP TABLE IF EXISTS budget_repository_test_budgets');
$this->connection->exec('DROP TABLE IF EXISTS budget_repository_test_categories');
$this->connection->exec(
'CREATE TABLE budget_repository_test_categories (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
user_id INT UNSIGNED NOT NULL
)'
);
$this->connection->exec(
'CREATE TABLE budget_repository_test_budgets (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
categorie_id INT UNSIGNED NOT NULL,
plan_summ DECIMAL(15,2) NOT NULL,
year SMALLINT UNSIGNED NOT NULL,
month TINYINT UNSIGNED NOT NULL,
type ENUM(\'income\',\'expense\') NOT NULL,
formula_pct_used DECIMAL(5,2) NULL,
UNIQUE KEY uq_period (categorie_id, year, month)
)'
);
$this->repository = new BudgetRepositoryTestDouble();
}
protected function tearDown(): void
{
Profiler::reset();
if (isset($this->connection)) {
try {
$this->connection->exec('DROP TABLE IF EXISTS budget_repository_test_budgets');
$this->connection->exec('DROP TABLE IF EXISTS budget_repository_test_categories');
} catch (MyException) {
}
}
$ref = new ReflectionClass(Database::class);
$prop = $ref->getProperty('_instances');
$prop->setAccessible(true);
$prop->setValue(null, []);
}
private function createCategory(int $user_id): int
{
$stmt = $this->connection->prepare('INSERT INTO budget_repository_test_categories (user_id) VALUES (:user_id)');
$stmt->execute(['user_id' => $user_id]);
return (int)$this->connection->lastInsertId();
}
public function testUpsertCreatesRow(): void
{
$categorie_id = $this->createCategory(1);
$this->repository->upsert($categorie_id, 2027, 3, 1000.50, 'expense');
$row = $this->repository->getItemWhere("categorie_id = $categorie_id AND year = 2027 AND month = 3");
$this->assertSame('1000.50', $row->plan_summ);
}
public function testUpsertUpdatesExistingRow(): void
{
$categorie_id = $this->createCategory(1);
$this->repository->upsert($categorie_id, 2027, 3, 1000, 'expense');
$this->repository->upsert($categorie_id, 2027, 3, 2500, 'expense');
$rows = $this->repository->getList('*', ['categorie_id' => $categorie_id]);
$this->assertCount(1, $rows);
$this->assertSame('2500.00', $rows[0]->plan_summ);
}
public function testUpsertStoresFormulaPctUsed(): void
{
$categorie_id = $this->createCategory(1);
$this->repository->upsert($categorie_id, 2027, 5, 300, 'expense', 30.5);
$row = $this->repository->getItemWhere("categorie_id = $categorie_id AND year = 2027 AND month = 5");
$this->assertSame('30.50', $row->formula_pct_used);
}
public function testGetYearReturnsOnlyUsersCategories(): void
{
$my_categorie_id = $this->createCategory(1);
$foreign_categorie_id = $this->createCategory(2);
$this->repository->upsert($my_categorie_id, 2027, 1, 100, 'income');
$this->repository->upsert($foreign_categorie_id, 2027, 1, 999, 'income');
$plan = $this->repository->getYear(1, 2027);
$this->assertArrayHasKey($my_categorie_id, $plan);
$this->assertArrayNotHasKey($foreign_categorie_id, $plan);
$this->assertSame(100.0, $plan[$my_categorie_id][1]['plan_summ']);
}
public function testGetYearFiltersByYear(): void
{
$categorie_id = $this->createCategory(1);
$this->repository->upsert($categorie_id, 2026, 1, 100, 'income');
$this->repository->upsert($categorie_id, 2027, 1, 200, 'income');
$plan = $this->repository->getYear(1, 2027);
$this->assertSame(200.0, $plan[$categorie_id][1]['plan_summ']);
$this->assertCount(1, $plan[$categorie_id]);
}
}