diff --git a/app/Models/Playlist.php b/app/Models/Playlist.php index 2a0527f..d24356f 100644 --- a/app/Models/Playlist.php +++ b/app/Models/Playlist.php @@ -43,11 +43,22 @@ class Playlist extends Model return false; } } - // Check time range + if ($this->active_from !== null && $this->active_until !== null) { - if (! now()->between($this->active_from, $this->active_until)) { - return false; + $now = now(); + + // Handle time ranges that span across midnight + if ($this->active_from > $this->active_until) { + // Time range spans midnight (e.g., 09:01 to 03:58) + if ($now >= $this->active_from || $now <= $this->active_until) { + return true; + } + } else { + if ($now >= $this->active_from && $now <= $this->active_until) { + return true; + } } + return false; } return true; diff --git a/tests/Feature/PlaylistSchedulingTest.php b/tests/Feature/PlaylistSchedulingTest.php new file mode 100644 index 0000000..43ad663 --- /dev/null +++ b/tests/Feature/PlaylistSchedulingTest.php @@ -0,0 +1,132 @@ +create(); + $device = Device::factory()->create(['user_id' => $user->id]); + + // Create two playlists with overlapping time ranges spanning midnight + $playlist1 = Playlist::factory()->create([ + 'device_id' => $device->id, + 'name' => 'Day until Deep Night Playlist', + 'is_active' => true, + 'active_from' => '09:01', + 'active_until' => '03:58', + 'weekdays' => null, // Active every day + ]); + + $playlist2 = Playlist::factory()->create([ + 'device_id' => $device->id, + 'name' => 'Early Morning Playlist', + 'is_active' => true, + 'active_from' => '04:00', + 'active_until' => '09:00', + 'weekdays' => null, // Active every day + ]); + + // Create plugins and playlist items + $plugin1 = Plugin::factory()->create(['name' => 'Day & Deep Night Plugin']); + $plugin2 = Plugin::factory()->create(['name' => 'Morning Plugin']); + + PlaylistItem::factory()->create([ + 'playlist_id' => $playlist1->id, + 'plugin_id' => $plugin1->id, + 'order' => 1, + 'is_active' => true, + ]); + + PlaylistItem::factory()->create([ + 'playlist_id' => $playlist2->id, + 'plugin_id' => $plugin2->id, + 'order' => 1, + 'is_active' => true, + ]); + + // Test at 10:00 AM - should get playlist2 (Early Morning Playlist) + Carbon::setTestNow(Carbon::create(2024, 1, 1, 4, 0, 0)); + + $nextItem = $device->getNextPlaylistItem(); + expect($nextItem)->not->toBeNull(); + expect($nextItem->plugin->name)->toBe('Morning Plugin'); + expect($nextItem->playlist->name)->toBe('Early Morning Playlist'); + + // Test at 2:00 AM - should get playlist1 (Day until Deep Night Playlist) + Carbon::setTestNow(Carbon::create(2024, 1, 1, 10, 0, 0)); + + $nextItem = $device->getNextPlaylistItem(); + expect($nextItem)->not->toBeNull(); + expect($nextItem->plugin->name)->toBe('Day & Deep Night Plugin'); + expect($nextItem->playlist->name)->toBe('Day until Deep Night Playlist'); + + // Test at 5:00 AM - should get playlist2 (Early Morning Playlist) + Carbon::setTestNow(Carbon::create(2024, 1, 1, 8, 0, 0)); + + $nextItem = $device->getNextPlaylistItem(); + expect($nextItem)->not->toBeNull(); + expect($nextItem->plugin->name)->toBe('Morning Plugin'); + expect($nextItem->playlist->name)->toBe('Early Morning Playlist'); + + // Test at 11:00 PM - should get playlist1 (Day until Deep Night Playlist) + Carbon::setTestNow(Carbon::create(2024, 1, 1, 23, 0, 0)); + + $nextItem = $device->getNextPlaylistItem(); + expect($nextItem)->not->toBeNull(); + expect($nextItem->plugin->name)->toBe('Day & Deep Night Plugin'); + expect($nextItem->playlist->name)->toBe('Day until Deep Night Playlist'); +}); + +test('playlist isActiveNow handles midnight spanning correctly', function () { + $playlist = Playlist::factory()->create([ + 'is_active' => true, + 'active_from' => '09:01', + 'active_until' => '03:58', + 'weekdays' => null, + ]); + + // Test at 2:00 AM - should be active + Carbon::setTestNow(Carbon::create(2024, 1, 1, 2, 0, 0)); + expect($playlist->isActiveNow())->toBeTrue(); + + // Test at 10:00 AM - should be active + Carbon::setTestNow(Carbon::create(2024, 1, 1, 10, 0, 0)); + expect($playlist->isActiveNow())->toBeTrue(); + + // Test at 5:00 AM - should NOT be active (gap between playlists) + Carbon::setTestNow(Carbon::create(2024, 1, 1, 5, 0, 0)); + expect($playlist->isActiveNow())->toBeFalse(); + + // Test at 8:00 AM - should NOT be active (gap between playlists) + Carbon::setTestNow(Carbon::create(2024, 1, 1, 8, 0, 0)); + expect($playlist->isActiveNow())->toBeFalse(); +}); + +test('playlist isActiveNow handles normal time ranges correctly', function () { + $playlist = Playlist::factory()->create([ + 'is_active' => true, + 'active_from' => '09:00', + 'active_until' => '17:00', + 'weekdays' => null, + ]); + + // Test at 10:00 AM - should be active + Carbon::setTestNow(Carbon::create(2024, 1, 1, 10, 0, 0)); + expect($playlist->isActiveNow())->toBeTrue(); + + // Test at 2:00 AM - should NOT be active + Carbon::setTestNow(Carbon::create(2024, 1, 1, 2, 0, 0)); + expect($playlist->isActiveNow())->toBeFalse(); + + // Test at 8:00 PM - should NOT be active + Carbon::setTestNow(Carbon::create(2024, 1, 1, 20, 0, 0)); + expect($playlist->isActiveNow())->toBeFalse(); +});