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