commit 08-2025
This commit is contained in:
parent
9ae662f63e
commit
480fdc65ed
404 changed files with 65310 additions and 2600431 deletions
184
tests/Feature/BusinessPlan/TreeCalcBotIntegrationTest.php
Normal file
184
tests/Feature/BusinessPlan/TreeCalcBotIntegrationTest.php
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\Feature\BusinessPlan;
|
||||
|
||||
use Tests\TestCase;
|
||||
use App\User;
|
||||
use App\Models\UserAccount;
|
||||
use App\Models\UserLevel;
|
||||
use App\Models\UserBusiness;
|
||||
use App\Models\UserBusinessStructure;
|
||||
use App\Services\BusinessPlan\TreeCalcBotOptimized;
|
||||
use App\Services\BusinessPlan\TreeCalcBot;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
class TreeCalcBotIntegrationTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
/** @test */
|
||||
public function optimized_version_can_replace_original_version()
|
||||
{
|
||||
// Create test data
|
||||
$user = User::factory()->create([
|
||||
'm_sponsor' => null,
|
||||
'm_level' => 1,
|
||||
'payment_account' => '2024-01-15',
|
||||
'active_date' => '2024-01-01'
|
||||
]);
|
||||
|
||||
UserAccount::factory()->create([
|
||||
'user_id' => $user->id,
|
||||
'first_name' => 'Test',
|
||||
'last_name' => 'User',
|
||||
'm_account' => 'TEST123'
|
||||
]);
|
||||
|
||||
UserLevel::factory()->create([
|
||||
'id' => 1,
|
||||
'name' => 'Bronze',
|
||||
'pos' => 1
|
||||
]);
|
||||
|
||||
// Test original version
|
||||
$originalBot = new TreeCalcBot(1, 2024, 'admin');
|
||||
$originalBot->initStructureAdmin(false);
|
||||
$originalItems = $originalBot->getItems();
|
||||
|
||||
// Test optimized version
|
||||
$optimizedBot = new TreeCalcBotOptimized(1, 2024, 'admin');
|
||||
$optimizedBot->initStructureAdmin(false);
|
||||
$optimizedItems = $optimizedBot->getItems();
|
||||
|
||||
// Both should return same number of items
|
||||
$this->assertEquals(count($originalItems), count($optimizedItems));
|
||||
|
||||
// Both should have same basic functionality
|
||||
$this->assertEquals($originalBot->isParentless(), $optimizedBot->isParentless());
|
||||
|
||||
// HTML output should be generated (length > 0)
|
||||
$this->assertGreaterThan(0, strlen($originalBot->makeHtmlTree()));
|
||||
$this->assertGreaterThan(0, strlen($optimizedBot->makeHtmlTree()));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function optimized_version_handles_memory_efficiently()
|
||||
{
|
||||
// Create multiple users to test memory efficiency
|
||||
$users = [];
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
$user = User::factory()->create([
|
||||
'm_sponsor' => null,
|
||||
'm_level' => 1,
|
||||
'payment_account' => '2024-01-15',
|
||||
'active_date' => '2024-01-01'
|
||||
]);
|
||||
|
||||
UserAccount::factory()->create([
|
||||
'user_id' => $user->id,
|
||||
'first_name' => 'User',
|
||||
'last_name' => $i,
|
||||
'm_account' => 'TEST' . $i
|
||||
]);
|
||||
|
||||
$users[] = $user;
|
||||
}
|
||||
|
||||
$startMemory = memory_get_usage();
|
||||
|
||||
$optimizedBot = new TreeCalcBotOptimized(1, 2024, 'admin');
|
||||
$optimizedBot->initStructureAdmin(false);
|
||||
|
||||
$endMemory = memory_get_usage();
|
||||
$memoryUsed = $endMemory - $startMemory;
|
||||
|
||||
// Memory usage should be reasonable (less than 5MB for 5 users)
|
||||
$this->assertLessThan(5 * 1024 * 1024, $memoryUsed);
|
||||
|
||||
// Should still function correctly
|
||||
$this->assertEquals(5, count($optimizedBot->getItems()));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function optimized_version_maintains_backward_compatibility()
|
||||
{
|
||||
$optimizedBot = new TreeCalcBotOptimized(1, 2024, 'admin');
|
||||
|
||||
// Test all public methods exist and are callable
|
||||
$this->assertTrue(method_exists($optimizedBot, 'initStructureAdmin'));
|
||||
$this->assertTrue(method_exists($optimizedBot, 'initStructureUser'));
|
||||
$this->assertTrue(method_exists($optimizedBot, 'getItems'));
|
||||
$this->assertTrue(method_exists($optimizedBot, 'makeHtmlTree'));
|
||||
$this->assertTrue(method_exists($optimizedBot, 'makeParentlessHtml'));
|
||||
$this->assertTrue(method_exists($optimizedBot, 'makeSponsorHtml'));
|
||||
$this->assertTrue(method_exists($optimizedBot, 'isParentless'));
|
||||
$this->assertTrue(method_exists($optimizedBot, 'getGrowthBonus'));
|
||||
$this->assertTrue(method_exists($optimizedBot, 'getKeybyLine'));
|
||||
|
||||
// Test static methods
|
||||
$this->assertTrue(method_exists($optimizedBot, 'isFromStored'));
|
||||
$this->assertTrue(method_exists($optimizedBot, 'addUserID'));
|
||||
|
||||
// Test magic methods for property access
|
||||
$date = $optimizedBot->__get('date');
|
||||
$this->assertNotNull($date);
|
||||
$this->assertEquals(1, $date->month);
|
||||
$this->assertEquals(2024, $date->year);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function optimized_version_produces_valid_html_output()
|
||||
{
|
||||
// Create test user
|
||||
$user = User::factory()->create([
|
||||
'm_sponsor' => null,
|
||||
'm_level' => 1,
|
||||
'payment_account' => '2024-01-15',
|
||||
'active_date' => '2024-01-01'
|
||||
]);
|
||||
|
||||
UserAccount::factory()->create([
|
||||
'user_id' => $user->id,
|
||||
'first_name' => 'Test',
|
||||
'last_name' => 'User'
|
||||
]);
|
||||
|
||||
$optimizedBot = new TreeCalcBotOptimized(1, 2024, 'admin');
|
||||
$optimizedBot->initStructureAdmin(false);
|
||||
|
||||
// Test HTML outputs
|
||||
$treeHtml = $optimizedBot->makeHtmlTree();
|
||||
$parentlessHtml = $optimizedBot->makeParentlessHtml();
|
||||
$sponsorHtml = $optimizedBot->makeSponsorHtml();
|
||||
|
||||
// All should produce valid HTML strings
|
||||
$this->assertIsString($treeHtml);
|
||||
$this->assertIsString($parentlessHtml);
|
||||
$this->assertIsString($sponsorHtml);
|
||||
|
||||
// Tree HTML should contain user data when users exist
|
||||
if (count($optimizedBot->getItems()) > 0) {
|
||||
$this->assertStringContainsString('Test User', $treeHtml);
|
||||
}
|
||||
|
||||
// HTML should be properly formed (basic check)
|
||||
$this->assertStringNotContainsString('><', $treeHtml . $parentlessHtml . $sponsorHtml);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function optimized_version_error_handling_works()
|
||||
{
|
||||
$optimizedBot = new TreeCalcBotOptimized(1, 2024, 'admin');
|
||||
|
||||
// Should handle non-existent user gracefully
|
||||
$optimizedBot->initStructureUser(999999);
|
||||
|
||||
// Should return empty results but not crash
|
||||
$this->assertEquals([], $optimizedBot->getItems());
|
||||
$this->assertFalse($optimizedBot->isParentless());
|
||||
|
||||
// Should handle method calls on empty state
|
||||
$this->assertEquals([], $optimizedBot->getGrowthBonus());
|
||||
$this->assertEquals(0, $optimizedBot->getKeybyLine(1, 'points'));
|
||||
}
|
||||
}
|
||||
297
tests/Unit/BusinessPlan/BusinessUserItemOptimizedTest.php
Normal file
297
tests/Unit/BusinessPlan/BusinessUserItemOptimizedTest.php
Normal file
|
|
@ -0,0 +1,297 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\Unit\BusinessPlan;
|
||||
|
||||
use Tests\TestCase;
|
||||
use App\User;
|
||||
use App\Models\UserBusiness;
|
||||
use App\Models\UserLevel;
|
||||
use App\Models\UserAccount;
|
||||
use App\Services\BusinessPlan\BusinessUserItemOptimized;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Carbon\Carbon;
|
||||
use stdClass;
|
||||
|
||||
class BusinessUserItemOptimizedTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
private $dateObj;
|
||||
private $businessUserItem;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->dateObj = new stdClass();
|
||||
$this->dateObj->month = 1;
|
||||
$this->dateObj->year = 2024;
|
||||
$this->dateObj->start_date = '2024-01-01 00:00:00';
|
||||
$this->dateObj->end_date = '2024-01-31 23:59:59';
|
||||
|
||||
$this->businessUserItem = new BusinessUserItemOptimized($this->dateObj);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function constructor_initializes_properties_correctly()
|
||||
{
|
||||
$businessUserItem = new BusinessUserItemOptimized($this->dateObj);
|
||||
|
||||
$this->assertEquals($this->dateObj, $businessUserItem->__get('date'));
|
||||
$this->assertEquals([], $businessUserItem->businessUserItems);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function makeUser_finds_existing_business_user()
|
||||
{
|
||||
// Create user and existing business data
|
||||
$user = User::factory()->create();
|
||||
$existingBusiness = UserBusiness::create([
|
||||
'user_id' => $user->id,
|
||||
'month' => 1,
|
||||
'year' => 2024,
|
||||
'sales_volume_KP_points' => 100
|
||||
]);
|
||||
|
||||
$this->businessUserItem->makeUser($user->id);
|
||||
|
||||
$this->assertEquals($existingBusiness->id, $this->businessUserItem->getBUser()->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function makeUser_handles_non_existent_user()
|
||||
{
|
||||
$this->businessUserItem->makeUser(999);
|
||||
|
||||
// Should not throw exception and should handle gracefully
|
||||
$this->assertNull($this->businessUserItem->getBUser());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function makeUserFromModel_throws_exception_for_invalid_user()
|
||||
{
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage('Invalid user model provided');
|
||||
|
||||
$invalidUser = new User(); // User without ID
|
||||
$this->businessUserItem->makeUserFromModel($invalidUser);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function makeUserFromModel_creates_business_user_from_valid_model()
|
||||
{
|
||||
// Create user with account and level
|
||||
$user = User::factory()->create([
|
||||
'm_level' => 1,
|
||||
'payment_account' => '2024-01-15',
|
||||
'active_date' => '2024-01-01'
|
||||
]);
|
||||
|
||||
$account = UserAccount::factory()->create([
|
||||
'user_id' => $user->id,
|
||||
'first_name' => 'John',
|
||||
'last_name' => 'Doe',
|
||||
'm_account' => 'TEST123'
|
||||
]);
|
||||
|
||||
$userLevel = UserLevel::factory()->create([
|
||||
'id' => 1,
|
||||
'name' => 'Bronze',
|
||||
'pos' => 1,
|
||||
'margin' => 10,
|
||||
'margin_shop' => 15,
|
||||
'qual_kp' => 100,
|
||||
'qual_pp' => 200
|
||||
]);
|
||||
|
||||
// Load user with relations
|
||||
$userWithRelations = User::with(['account', 'userLevel'])->find($user->id);
|
||||
|
||||
$this->businessUserItem->makeUserFromModel($userWithRelations);
|
||||
|
||||
$bUser = $this->businessUserItem->getBUser();
|
||||
$this->assertNotNull($bUser);
|
||||
$this->assertEquals($user->id, $bUser->user_id);
|
||||
$this->assertEquals('John', $bUser->first_name);
|
||||
$this->assertEquals('Doe', $bUser->last_name);
|
||||
$this->assertEquals('Bronze', $bUser->user_level_name);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function addBusinessLinePoints_handles_non_existent_line()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
$this->businessUserItem->makeUser($user->id);
|
||||
|
||||
// This should log a warning but not throw an exception
|
||||
$this->businessUserItem->addBusinessLinePoints(1, 100);
|
||||
|
||||
// Test passes if no exception is thrown
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function addBusinessLinePoints_adds_points_correctly()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
$this->businessUserItem->makeUser($user->id);
|
||||
|
||||
// First, add a business line
|
||||
$obj = new stdClass();
|
||||
$obj->points = 50;
|
||||
$this->businessUserItem->addBusinessLineToUser(1, $obj);
|
||||
|
||||
// Then add more points
|
||||
$this->businessUserItem->addBusinessLinePoints(1, 100);
|
||||
|
||||
$bUser = $this->businessUserItem->getBUser();
|
||||
$this->assertEquals(150, $bUser->business_lines[1]->points);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function addTotalTP_adds_points_with_type_safety()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
$this->businessUserItem->makeUser($user->id);
|
||||
|
||||
$this->businessUserItem->addTotalTP('100.5'); // String should be converted to float
|
||||
$this->businessUserItem->addTotalTP(50);
|
||||
|
||||
$bUser = $this->businessUserItem->getBUser();
|
||||
$this->assertEquals(150.5, $bUser->total_pp);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function isQualKP_returns_correct_boolean()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
$userLevel = UserLevel::factory()->create([
|
||||
'id' => 1,
|
||||
'qual_kp' => 100
|
||||
]);
|
||||
|
||||
$this->businessUserItem->makeUser($user->id);
|
||||
|
||||
// Manually set values for testing
|
||||
$bUser = $this->businessUserItem->getBUser();
|
||||
$bUser->sales_volume_points_KP_sum = 150;
|
||||
$bUser->qual_kp = 100;
|
||||
|
||||
$this->assertTrue($this->businessUserItem->isQualKP());
|
||||
|
||||
$bUser->sales_volume_points_KP_sum = 50;
|
||||
$this->assertFalse($this->businessUserItem->isQualKP());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function getRestQualKP_returns_positive_value_or_zero()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
$this->businessUserItem->makeUser($user->id);
|
||||
|
||||
$bUser = $this->businessUserItem->getBUser();
|
||||
$bUser->sales_volume_points_KP_sum = 150;
|
||||
$bUser->qual_kp = 100;
|
||||
|
||||
$this->assertEquals(50, $this->businessUserItem->getRestQualKP());
|
||||
|
||||
$bUser->sales_volume_points_KP_sum = 50;
|
||||
$this->assertEquals(0, $this->businessUserItem->getRestQualKP()); // Should not be negative
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function getCommissionTotal_calculates_correctly()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
$this->businessUserItem->makeUser($user->id);
|
||||
|
||||
$bUser = $this->businessUserItem->getBUser();
|
||||
$bUser->commission_shop_sales = 10.50;
|
||||
$bUser->commission_pp_total = 25.75;
|
||||
$bUser->commission_growth_total = 15.25;
|
||||
|
||||
$total = $this->businessUserItem->getCommissionTotal();
|
||||
$this->assertEquals(51.50, $total);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function checkSponsor_handles_user_without_sponsor()
|
||||
{
|
||||
$user = User::factory()->create(['m_sponsor' => null]);
|
||||
$this->businessUserItem->makeUser($user->id);
|
||||
|
||||
$this->businessUserItem->checkSponsor($user);
|
||||
|
||||
$bUser = $this->businessUserItem->getBUser();
|
||||
$this->assertFalse($bUser->sponsor->is_sponsor);
|
||||
$this->assertEquals('Keinen Sponsor zugewiesen', $bUser->sponsor->full_name);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function isSave_returns_correct_boolean()
|
||||
{
|
||||
// New business user item should not be saved
|
||||
$this->assertFalse($this->businessUserItem->isSave());
|
||||
|
||||
// Create and save a business user
|
||||
$user = User::factory()->create();
|
||||
$business = UserBusiness::create([
|
||||
'user_id' => $user->id,
|
||||
'month' => 1,
|
||||
'year' => 2024
|
||||
]);
|
||||
|
||||
$this->businessUserItem->makeUser($user->id);
|
||||
$this->assertTrue($this->businessUserItem->isSave());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function magic_get_method_returns_properties()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
$this->businessUserItem->makeUser($user->id);
|
||||
|
||||
$userId = $this->businessUserItem->__get('user_id');
|
||||
$this->assertEquals($user->id, $userId);
|
||||
|
||||
$nullValue = $this->businessUserItem->__get('non_existent_property');
|
||||
$this->assertNull($nullValue);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function readParentsBusinessUsers_loads_child_users()
|
||||
{
|
||||
// Create parent user
|
||||
$parentUser = User::factory()->create([
|
||||
'payment_account' => '2024-01-15',
|
||||
'active_date' => '2024-01-01',
|
||||
'm_level' => 1
|
||||
]);
|
||||
|
||||
// Create child users
|
||||
$childUser1 = User::factory()->create([
|
||||
'm_sponsor' => $parentUser->id,
|
||||
'payment_account' => '2024-01-15',
|
||||
'active_date' => '2024-01-01',
|
||||
'm_level' => 1
|
||||
]);
|
||||
|
||||
$childUser2 = User::factory()->create([
|
||||
'm_sponsor' => $parentUser->id,
|
||||
'payment_account' => '2024-01-15',
|
||||
'active_date' => '2024-01-01',
|
||||
'm_level' => 1
|
||||
]);
|
||||
|
||||
// Create accounts for users
|
||||
UserAccount::factory()->create(['user_id' => $parentUser->id]);
|
||||
UserAccount::factory()->create(['user_id' => $childUser1->id]);
|
||||
UserAccount::factory()->create(['user_id' => $childUser2->id]);
|
||||
|
||||
$this->businessUserItem->makeUser($parentUser->id);
|
||||
$this->businessUserItem->readParentsBusinessUsers();
|
||||
|
||||
// Should have loaded 2 child business users
|
||||
$this->assertCount(2, $this->businessUserItem->businessUserItems);
|
||||
}
|
||||
}
|
||||
285
tests/Unit/BusinessPlan/BusinessUserRepositoryTest.php
Normal file
285
tests/Unit/BusinessPlan/BusinessUserRepositoryTest.php
Normal file
|
|
@ -0,0 +1,285 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\Unit\BusinessPlan;
|
||||
|
||||
use Tests\TestCase;
|
||||
use App\User;
|
||||
use App\Models\UserAccount;
|
||||
use App\Models\UserBusinessStructure;
|
||||
use App\Services\BusinessPlan\BusinessUserRepository;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
class BusinessUserRepositoryTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
private $repository;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->repository = new BusinessUserRepository(1, 2024);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function constructor_initializes_dates_correctly()
|
||||
{
|
||||
$repository = new BusinessUserRepository(3, 2024);
|
||||
|
||||
// Using reflection to access private properties for testing
|
||||
$reflection = new \ReflectionClass($repository);
|
||||
$monthProperty = $reflection->getProperty('month');
|
||||
$monthProperty->setAccessible(true);
|
||||
$yearProperty = $reflection->getProperty('year');
|
||||
$yearProperty->setAccessible(true);
|
||||
|
||||
$this->assertEquals(3, $monthProperty->getValue($repository));
|
||||
$this->assertEquals(2024, $yearProperty->getValue($repository));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function getStoredStructure_returns_completed_structure()
|
||||
{
|
||||
$structure = UserBusinessStructure::create([
|
||||
'month' => 1,
|
||||
'year' => 2024,
|
||||
'structure' => json_encode([]),
|
||||
'completed' => true
|
||||
]);
|
||||
|
||||
$result = $this->repository->getStoredStructure();
|
||||
|
||||
$this->assertNotNull($result);
|
||||
$this->assertEquals($structure->id, $result->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function getStoredStructure_returns_null_for_incomplete_structure()
|
||||
{
|
||||
UserBusinessStructure::create([
|
||||
'month' => 1,
|
||||
'year' => 2024,
|
||||
'structure' => json_encode([]),
|
||||
'completed' => false
|
||||
]);
|
||||
|
||||
$result = $this->repository->getStoredStructure();
|
||||
|
||||
$this->assertNull($result);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function getRootUsers_returns_users_with_relations()
|
||||
{
|
||||
// Create root users (no sponsor)
|
||||
$rootUser1 = User::factory()->create([
|
||||
'm_sponsor' => null,
|
||||
'm_level' => 1,
|
||||
'payment_account' => '2024-01-15',
|
||||
'active_date' => '2024-01-01'
|
||||
]);
|
||||
|
||||
$rootUser2 = User::factory()->create([
|
||||
'm_sponsor' => null,
|
||||
'm_level' => 2,
|
||||
'payment_account' => '2024-01-15',
|
||||
'active_date' => '2024-01-01'
|
||||
]);
|
||||
|
||||
// Create non-root user (has sponsor)
|
||||
$childUser = User::factory()->create([
|
||||
'm_sponsor' => $rootUser1->id,
|
||||
'm_level' => 1,
|
||||
'payment_account' => '2024-01-15',
|
||||
'active_date' => '2024-01-01'
|
||||
]);
|
||||
|
||||
// Create accounts
|
||||
UserAccount::factory()->create(['user_id' => $rootUser1->id]);
|
||||
UserAccount::factory()->create(['user_id' => $rootUser2->id]);
|
||||
UserAccount::factory()->create(['user_id' => $childUser->id]);
|
||||
|
||||
$result = $this->repository->getRootUsers();
|
||||
|
||||
// Should return only root users (2), not child user
|
||||
$this->assertEquals(2, $result->count());
|
||||
|
||||
// Verify relations are loaded
|
||||
$firstUser = $result->first();
|
||||
$this->assertTrue($firstUser->relationLoaded('account'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function getUserWithRelations_returns_user_with_loaded_relations()
|
||||
{
|
||||
$user = User::factory()->create([
|
||||
'm_level' => 1,
|
||||
'payment_account' => '2024-01-15'
|
||||
]);
|
||||
|
||||
UserAccount::factory()->create(['user_id' => $user->id]);
|
||||
|
||||
$result = $this->repository->getUserWithRelations($user->id);
|
||||
|
||||
$this->assertNotNull($result);
|
||||
$this->assertEquals($user->id, $result->id);
|
||||
$this->assertTrue($result->relationLoaded('account'));
|
||||
$this->assertTrue($result->relationLoaded('userLevel'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function getUserWithRelations_returns_null_for_non_existent_user()
|
||||
{
|
||||
$result = $this->repository->getUserWithRelations(999);
|
||||
|
||||
$this->assertNull($result);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function getParentlessUsers_excludes_processed_user_ids()
|
||||
{
|
||||
// Create users
|
||||
$user1 = User::factory()->create([
|
||||
'm_level' => 1,
|
||||
'payment_account' => '2024-01-15',
|
||||
'active_date' => '2024-01-01'
|
||||
]);
|
||||
|
||||
$user2 = User::factory()->create([
|
||||
'm_level' => 1,
|
||||
'payment_account' => '2024-01-15',
|
||||
'active_date' => '2024-01-01'
|
||||
]);
|
||||
|
||||
$user3 = User::factory()->create([
|
||||
'm_level' => 1,
|
||||
'payment_account' => '2024-01-15',
|
||||
'active_date' => '2024-01-01'
|
||||
]);
|
||||
|
||||
// Create accounts
|
||||
UserAccount::factory()->create(['user_id' => $user1->id]);
|
||||
UserAccount::factory()->create(['user_id' => $user2->id]);
|
||||
UserAccount::factory()->create(['user_id' => $user3->id]);
|
||||
|
||||
// Exclude user1 and user2
|
||||
$excludeIds = [$user1->id, $user2->id];
|
||||
|
||||
$result = $this->repository->getParentlessUsers($excludeIds);
|
||||
|
||||
// Should only return user3
|
||||
$this->assertEquals(1, $result->count());
|
||||
$this->assertEquals($user3->id, $result->first()->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function getSponsorForUser_returns_sponsor_user()
|
||||
{
|
||||
// Create sponsor
|
||||
$sponsor = User::factory()->create(['m_level' => 2]);
|
||||
UserAccount::factory()->create(['user_id' => $sponsor->id]);
|
||||
|
||||
// Create user with sponsor
|
||||
$user = User::factory()->create(['m_sponsor' => $sponsor->id]);
|
||||
UserAccount::factory()->create(['user_id' => $user->id]);
|
||||
|
||||
$result = $this->repository->getSponsorForUser($user->id);
|
||||
|
||||
$this->assertNotNull($result);
|
||||
$this->assertEquals($sponsor->id, $result->id);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function getSponsorForUser_returns_null_for_user_without_sponsor()
|
||||
{
|
||||
$user = User::factory()->create(['m_sponsor' => null]);
|
||||
|
||||
$result = $this->repository->getSponsorForUser($user->id);
|
||||
|
||||
$this->assertNull($result);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function caching_works_correctly_for_root_users()
|
||||
{
|
||||
// Clear cache first
|
||||
Cache::flush();
|
||||
|
||||
// Create root user
|
||||
$rootUser = User::factory()->create([
|
||||
'm_sponsor' => null,
|
||||
'm_level' => 1,
|
||||
'payment_account' => '2024-01-15',
|
||||
'active_date' => '2024-01-01'
|
||||
]);
|
||||
UserAccount::factory()->create(['user_id' => $rootUser->id]);
|
||||
|
||||
// First call should hit database and cache result
|
||||
$result1 = $this->repository->getRootUsers();
|
||||
$this->assertEquals(1, $result1->count());
|
||||
|
||||
// Verify cache was set
|
||||
$cacheKey = "root_users_1_2024";
|
||||
$this->assertTrue(Cache::has($cacheKey));
|
||||
|
||||
// Second call should use cache
|
||||
$result2 = $this->repository->getRootUsers();
|
||||
$this->assertEquals(1, $result2->count());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function lazy_loading_yields_users_in_batches()
|
||||
{
|
||||
// Create multiple users
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
$user = User::factory()->create([
|
||||
'm_level' => 1,
|
||||
'payment_account' => '2024-01-15',
|
||||
'active_date' => '2024-01-01'
|
||||
]);
|
||||
UserAccount::factory()->create(['user_id' => $user->id]);
|
||||
}
|
||||
|
||||
$count = 0;
|
||||
foreach ($this->repository->getParentlessUsers([]) as $user) {
|
||||
$count++;
|
||||
$this->assertInstanceOf(User::class, $user);
|
||||
$this->assertTrue($user->relationLoaded('account'));
|
||||
}
|
||||
|
||||
$this->assertEquals(5, $count);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function memory_efficient_processing_works()
|
||||
{
|
||||
// Create many users to test memory efficiency
|
||||
for ($i = 0; $i < 10; $i++) {
|
||||
$user = User::factory()->create([
|
||||
'm_level' => 1,
|
||||
'payment_account' => '2024-01-15',
|
||||
'active_date' => '2024-01-01'
|
||||
]);
|
||||
UserAccount::factory()->create(['user_id' => $user->id]);
|
||||
}
|
||||
|
||||
$startMemory = memory_get_usage();
|
||||
|
||||
// Process users lazily
|
||||
$count = 0;
|
||||
foreach ($this->repository->getParentlessUsers([]) as $user) {
|
||||
$count++;
|
||||
// Simulate some processing
|
||||
$user->toArray();
|
||||
}
|
||||
|
||||
$endMemory = memory_get_usage();
|
||||
$memoryUsed = $endMemory - $startMemory;
|
||||
|
||||
$this->assertEquals(10, $count);
|
||||
// Memory usage should be reasonable (less than 10MB)
|
||||
$this->assertLessThan(10 * 1024 * 1024, $memoryUsed);
|
||||
}
|
||||
}
|
||||
311
tests/Unit/BusinessPlan/TreeCalcBotOptimizedTest.php
Normal file
311
tests/Unit/BusinessPlan/TreeCalcBotOptimizedTest.php
Normal file
|
|
@ -0,0 +1,311 @@
|
|||
<?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);
|
||||
}
|
||||
}
|
||||
254
tests/Unit/BusinessPlan/TreeHtmlRendererTest.php
Normal file
254
tests/Unit/BusinessPlan/TreeHtmlRendererTest.php
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\Unit\BusinessPlan;
|
||||
|
||||
use Tests\TestCase;
|
||||
use App\Services\BusinessPlan\TreeHtmlRenderer;
|
||||
use App\Services\BusinessPlan\BusinessUserItemOptimized;
|
||||
use stdClass;
|
||||
|
||||
class TreeHtmlRendererTest extends TestCase
|
||||
{
|
||||
private $renderer;
|
||||
private $dateObj;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->renderer = new TreeHtmlRenderer('admin');
|
||||
|
||||
$this->dateObj = new stdClass();
|
||||
$this->dateObj->month = 1;
|
||||
$this->dateObj->year = 2024;
|
||||
$this->dateObj->start_date = '2024-01-01 00:00:00';
|
||||
$this->dateObj->end_date = '2024-01-31 23:59:59';
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function constructor_sets_init_from_correctly()
|
||||
{
|
||||
$adminRenderer = new TreeHtmlRenderer('admin');
|
||||
$memberRenderer = new TreeHtmlRenderer('member');
|
||||
$defaultRenderer = new TreeHtmlRenderer();
|
||||
|
||||
// Using reflection to access private property
|
||||
$reflection = new \ReflectionClass(TreeHtmlRenderer::class);
|
||||
$property = $reflection->getProperty('initFrom');
|
||||
$property->setAccessible(true);
|
||||
|
||||
$this->assertEquals('admin', $property->getValue($adminRenderer));
|
||||
$this->assertEquals('member', $property->getValue($memberRenderer));
|
||||
$this->assertEquals('member', $property->getValue($defaultRenderer));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function renderTree_returns_info_message_for_empty_array()
|
||||
{
|
||||
$result = $this->renderer->renderTree([]);
|
||||
|
||||
$this->assertStringContainsString('Keine Business-User gefunden', $result);
|
||||
$this->assertStringContainsString('alert-info', $result);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function renderTree_generates_html_structure_for_business_users()
|
||||
{
|
||||
// Create mock business user items
|
||||
$businessUsers = [
|
||||
$this->createMockBusinessUser(1, 'John', 'Doe', 'john@example.com', true),
|
||||
$this->createMockBusinessUser(2, 'Jane', 'Smith', 'jane@example.com', false)
|
||||
];
|
||||
|
||||
$result = $this->renderer->renderTree($businessUsers);
|
||||
|
||||
// Check basic HTML structure
|
||||
$this->assertStringContainsString('<ol class="dd-list">', $result);
|
||||
$this->assertStringContainsString('</ol>', $result);
|
||||
$this->assertStringContainsString('dd-item', $result);
|
||||
|
||||
// Check user data is included
|
||||
$this->assertStringContainsString('John Doe', $result);
|
||||
$this->assertStringContainsString('Jane Smith', $result);
|
||||
$this->assertStringContainsString('john@example.com', $result);
|
||||
$this->assertStringContainsString('jane@example.com', $result);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function renderTree_includes_admin_buttons_for_admin_init()
|
||||
{
|
||||
$adminRenderer = new TreeHtmlRenderer('admin');
|
||||
$businessUsers = [
|
||||
$this->createMockBusinessUser(1, 'John', 'Doe', 'john@example.com', true)
|
||||
];
|
||||
|
||||
$result = $adminRenderer->renderTree($businessUsers);
|
||||
|
||||
// Should include calculator button for admin
|
||||
$this->assertStringContainsString('fa-calculator', $result);
|
||||
$this->assertStringContainsString('business-user-detail', $result);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function renderTree_excludes_admin_buttons_for_member_init()
|
||||
{
|
||||
$memberRenderer = new TreeHtmlRenderer('member');
|
||||
$businessUsers = [
|
||||
$this->createMockBusinessUser(1, 'John', 'Doe', 'john@example.com', true)
|
||||
];
|
||||
|
||||
$result = $memberRenderer->renderTree($businessUsers);
|
||||
|
||||
// Should not include calculator button for regular members
|
||||
$this->assertStringNotContainsString('fa-calculator', $result);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function renderTree_handles_inactive_accounts_correctly()
|
||||
{
|
||||
$businessUsers = [
|
||||
$this->createMockBusinessUser(1, 'Active', 'User', 'active@example.com', true),
|
||||
$this->createMockBusinessUser(2, 'Inactive', 'User', 'inactive@example.com', false)
|
||||
];
|
||||
|
||||
$result = $this->renderer->renderTree($businessUsers);
|
||||
|
||||
// Active user should have primary color icon
|
||||
$this->assertStringContainsString('text-primary', $result);
|
||||
// Inactive user should have danger/muted styling
|
||||
$this->assertStringContainsString('text-danger', $result);
|
||||
$this->assertStringContainsString('text-muted', $result);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function renderParentless_returns_empty_message_for_empty_array()
|
||||
{
|
||||
$result = $this->renderer->renderParentless([]);
|
||||
|
||||
$this->assertStringContainsString('Keine parentlosen User gefunden', $result);
|
||||
$this->assertStringContainsString('alert-info', $result);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function renderParentless_generates_list_for_parentless_users()
|
||||
{
|
||||
$parentlessUsers = [
|
||||
$this->createMockBusinessUser(1, 'Orphan', 'User', 'orphan@example.com', true)
|
||||
];
|
||||
|
||||
$result = $this->renderer->renderParentless($parentlessUsers);
|
||||
|
||||
$this->assertStringContainsString('dd-item', $result);
|
||||
$this->assertStringContainsString('Orphan User', $result);
|
||||
$this->assertStringContainsString('orphan@example.com', $result);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function renderSponsor_returns_no_sponsor_message_for_null()
|
||||
{
|
||||
$result = $this->renderer->renderSponsor(null);
|
||||
|
||||
$this->assertStringContainsString('alert-warning', $result);
|
||||
$this->assertStringContainsString('team.no_sponsor_assigned', $result);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function renderSponsor_generates_sponsor_html()
|
||||
{
|
||||
$sponsor = $this->createMockBusinessUser(1, 'Sponsor', 'User', 'sponsor@example.com', true);
|
||||
|
||||
$result = $this->renderer->renderSponsor($sponsor);
|
||||
|
||||
$this->assertStringContainsString('dd-item', $result);
|
||||
$this->assertStringContainsString('Sponsor User', $result);
|
||||
$this->assertStringContainsString('sponsor@example.com', $result);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function renderSponsor_includes_admin_details_for_admin_init()
|
||||
{
|
||||
$adminRenderer = new TreeHtmlRenderer('admin');
|
||||
$sponsor = $this->createMockBusinessUser(1, 'Sponsor', 'User', 'sponsor@example.com', true);
|
||||
|
||||
// Set some business data
|
||||
$sponsor->sales_volume_points_KP_sum = 1000;
|
||||
$sponsor->sales_volume_total_sum = 5000;
|
||||
|
||||
$result = $adminRenderer->renderSponsor($sponsor);
|
||||
|
||||
$this->assertStringContainsString('1000', $result);
|
||||
$this->assertStringContainsString('5000', $result);
|
||||
$this->assertStringContainsString('total_points', $result);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function renderItem_handles_deep_nesting()
|
||||
{
|
||||
// Create business user with nested children
|
||||
$parentUser = $this->createMockBusinessUser(1, 'Parent', 'User', 'parent@example.com', true);
|
||||
$childUser = $this->createMockBusinessUser(2, 'Child', 'User', 'child@example.com', true);
|
||||
|
||||
// Set up nesting
|
||||
$parentUser->businessUserItems = [$childUser];
|
||||
|
||||
$result = $this->renderer->renderTree([$parentUser]);
|
||||
|
||||
// Should contain both parent and child
|
||||
$this->assertStringContainsString('Parent User', $result);
|
||||
$this->assertStringContainsString('Child User', $result);
|
||||
|
||||
// Should have nested structure
|
||||
$this->assertStringContainsString('<ol class="dd-list dd-nodrag">', $result);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function html_output_is_properly_escaped()
|
||||
{
|
||||
$businessUsers = [
|
||||
$this->createMockBusinessUser(1, 'John <script>', 'Doe & Co', 'john@example.com', true)
|
||||
];
|
||||
|
||||
$result = $this->renderer->renderTree($businessUsers);
|
||||
|
||||
// HTML should be escaped
|
||||
$this->assertStringNotContainsString('<script>', $result);
|
||||
$this->assertStringContainsString('<script>', $result);
|
||||
$this->assertStringContainsString('&', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to create mock business user
|
||||
*/
|
||||
private function createMockBusinessUser($id, $firstName, $lastName, $email, $activeAccount)
|
||||
{
|
||||
$businessUser = new BusinessUserItemOptimized($this->dateObj);
|
||||
|
||||
// Create a mock b_user object
|
||||
$bUser = new stdClass();
|
||||
$bUser->user_id = $id;
|
||||
$bUser->first_name = $firstName;
|
||||
$bUser->last_name = $lastName;
|
||||
$bUser->email = $email;
|
||||
$bUser->active_account = $activeAccount;
|
||||
$bUser->user_level_name = 'Bronze';
|
||||
$bUser->m_account = 'TEST' . $id;
|
||||
$bUser->user_birthday = '1990-01-01';
|
||||
$bUser->user_phone = '+1234567890';
|
||||
$bUser->sales_volume_points_KP_sum = 100;
|
||||
$bUser->sales_volume_KP_points = 50;
|
||||
$bUser->sales_volume_points_shop = 50;
|
||||
$bUser->sales_volume_total_sum = 1000;
|
||||
$bUser->sales_volume_total = 500;
|
||||
$bUser->sales_volume_total_shop = 500;
|
||||
$bUser->payment_account_date = '2024-01-15';
|
||||
$bUser->businessUserItems = [];
|
||||
|
||||
// Use reflection to set private property
|
||||
$reflection = new \ReflectionClass($businessUser);
|
||||
$property = $reflection->getProperty('b_user');
|
||||
$property->setAccessible(true);
|
||||
$property->setValue($businessUser, $bUser);
|
||||
|
||||
return $businessUser;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue