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]); } }