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