311 lines
No EOL
8.8 KiB
PHP
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);
|
|
}
|
|
} |