mivita/tests/Unit/BusinessPlan/TreeCalcBotOptimizedTest.php
2025-08-12 18:01:59 +02:00

311 lines
No EOL
8.8 KiB
PHP

<?php
namespace Tests\Unit\BusinessPlan;
use Tests\TestCase;
use App\User;
use App\Models\UserBusinessStructure;
use App\Services\BusinessPlan\TreeCalcBotOptimized;
use App\Services\BusinessPlan\BusinessUserRepository;
use App\Services\BusinessPlan\TreeHtmlRenderer;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Mockery;
class TreeCalcBotOptimizedTest extends TestCase
{
use RefreshDatabase;
private $treeCalcBot;
private $mockRepository;
private $mockRenderer;
private $mockLogger;
protected function setUp(): void
{
parent::setUp();
$this->mockRepository = Mockery::mock(BusinessUserRepository::class);
$this->mockRenderer = Mockery::mock(TreeHtmlRenderer::class);
$this->mockLogger = Mockery::mock(\Psr\Log\LoggerInterface::class);
$this->treeCalcBot = new TreeCalcBotOptimized(
1, // month
2024, // year
'admin',
$this->mockRepository,
$this->mockRenderer,
$this->mockLogger
);
}
protected function tearDown(): void
{
Mockery::close();
parent::tearDown();
}
/** @test */
public function constructor_validates_month_boundaries()
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Invalid month: 13');
new TreeCalcBotOptimized(13, 2024);
}
/** @test */
public function constructor_validates_year_boundaries()
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Invalid year: 2019');
new TreeCalcBotOptimized(1, 2019);
}
/** @test */
public function constructor_initializes_date_object_correctly()
{
$treeCalcBot = new TreeCalcBotOptimized(3, 2024);
$date = $treeCalcBot->__get('date');
$this->assertEquals(3, $date->month);
$this->assertEquals(2024, $date->year);
$this->assertStringStartsWith('2024-03-01', $date->start_date);
$this->assertStringStartsWith('2024-03-31', $date->end_date);
}
/** @test */
public function isFromStored_returns_completed_structure()
{
// Create completed structure
$structure = UserBusinessStructure::create([
'month' => 1,
'year' => 2024,
'structure' => [],
'completed' => true
]);
$result = TreeCalcBotOptimized::isFromStored(1, 2024);
$this->assertNotNull($result);
$this->assertEquals($structure->id, $result->id);
}
/** @test */
public function isFromStored_returns_null_for_incomplete_structure()
{
// Create incomplete structure
UserBusinessStructure::create([
'month' => 1,
'year' => 2024,
'structure' => [],
'completed' => false
]);
$result = TreeCalcBotOptimized::isFromStored(1, 2024);
$this->assertNull($result);
}
/** @test */
public function initStructureAdmin_uses_stored_structure_when_available()
{
$mockStructure = new UserBusinessStructure();
$mockStructure->structure = [];
$mockStructure->parentless = [];
$this->mockRepository
->shouldReceive('getStoredStructure')
->once()
->andReturn($mockStructure);
$this->mockLogger
->shouldReceive('info')
->once()
->with('Loading stored business structure for 1/2024');
$this->treeCalcBot->initStructureAdmin(true);
}
/** @test */
public function initStructureAdmin_builds_fresh_when_no_stored_structure()
{
$this->mockRepository
->shouldReceive('getStoredStructure')
->once()
->andReturn(null);
$this->mockRepository
->shouldReceive('getRootUsers')
->once()
->andReturn(collect([]));
$this->mockLogger
->shouldReceive('info')
->once()
->with('Building fresh business structure for 1/2024');
$this->mockLogger
->shouldReceive('info')
->once()
->with('Loaded 0 root users with optimized relations. Memory used: 0 B');
$this->treeCalcBot->initStructureAdmin(true);
}
/** @test */
public function initStructureUser_handles_non_existent_user()
{
$this->mockRepository
->shouldReceive('getUserWithRelations')
->with(999)
->once()
->andReturn(null);
$this->mockLogger
->shouldReceive('info')
->once()
->with('Initializing structure for user: 999');
$this->mockLogger
->shouldReceive('warning')
->once()
->with('User not found: 999');
$this->treeCalcBot->initStructureUser(999);
}
/** @test */
public function getGrowthBonus_returns_empty_array_when_no_business_user()
{
$result = $this->treeCalcBot->getGrowthBonus();
$this->assertEquals([], $result);
}
/** @test */
public function getKeybyLine_returns_zero_when_no_business_user()
{
$result = $this->treeCalcBot->getKeybyLine(1, 'points');
$this->assertEquals(0, $result);
}
/** @test */
public function makeHtmlTree_delegates_to_renderer()
{
$expectedHtml = '<div>Test HTML</div>';
$this->mockRenderer
->shouldReceive('renderTree')
->once()
->with([])
->andReturn($expectedHtml);
$result = $this->treeCalcBot->makeHtmlTree();
$this->assertEquals($expectedHtml, $result);
}
/** @test */
public function makeParentlessHtml_delegates_to_renderer()
{
$expectedHtml = '<div>Parentless HTML</div>';
$this->mockRenderer
->shouldReceive('renderParentless')
->once()
->with([])
->andReturn($expectedHtml);
$result = $this->treeCalcBot->makeParentlessHtml();
$this->assertEquals($expectedHtml, $result);
}
/** @test */
public function isParentless_returns_false_when_empty()
{
$result = $this->treeCalcBot->isParentless();
$this->assertFalse($result);
}
/** @test */
public function getItems_returns_business_users_array()
{
$result = $this->treeCalcBot->getItems();
$this->assertEquals([], $result);
}
/** @test */
public function magic_get_method_returns_correct_properties()
{
$date = $this->treeCalcBot->__get('date');
$businessUsers = $this->treeCalcBot->__get('business_users');
$parentless = $this->treeCalcBot->__get('parentless');
$this->assertNotNull($date);
$this->assertEquals([], $businessUsers);
$this->assertEquals([], $parentless);
}
/** @test */
public function magic_get_method_throws_exception_for_invalid_property()
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Property invalid_property does not exist');
$this->treeCalcBot->__get('invalid_property');
}
/** @test */
public function magic_set_method_allows_setting_valid_properties()
{
$testArray = ['test'];
$this->treeCalcBot->__set('business_users', $testArray);
$result = $this->treeCalcBot->__get('business_users');
$this->assertEquals($testArray, $result);
}
/** @test */
public function magic_set_method_throws_exception_for_invalid_property()
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Property invalid_property cannot be set');
$this->treeCalcBot->__set('invalid_property', 'value');
}
/** @test */
public function memory_monitoring_detects_high_usage()
{
// This test would need reflection to access private methods
// For now, we'll test the public interface
$this->mockLogger
->shouldReceive('info')
->once()
->with('Building fresh business structure for 1/2024');
$this->mockLogger
->shouldReceive('info')
->once()
->with('Loaded 0 root users with optimized relations. Memory used: 0 B');
$this->mockRepository
->shouldReceive('getStoredStructure')
->once()
->andReturn(null);
$this->mockRepository
->shouldReceive('getRootUsers')
->once()
->andReturn(collect([]));
$this->treeCalcBot->initStructureAdmin(false);
}
}