128 lines
4.7 KiB
Python
128 lines
4.7 KiB
Python
from django.test import TestCase
|
|
from django.db import IntegrityError, transaction
|
|
from core.models import (
|
|
AppUser, Library, LibraryMember, Genre, ContentRating, MediaSource,
|
|
Series, MediaItem, Channel, ScheduleTemplate, ScheduleBlock, Airing
|
|
)
|
|
from datetime import time
|
|
from django.utils import timezone
|
|
from uuid import uuid4
|
|
|
|
class PytvCoreTests(TestCase):
|
|
def setUp(self):
|
|
self.user1 = AppUser.objects.create_user(username="testuser1", email="test1@example.com", password="password123")
|
|
self.user2 = AppUser.objects.create_user(username="testuser2", email="test2@example.com", password="password123")
|
|
|
|
def test_user_and_library_creation(self):
|
|
# Create library
|
|
lib = Library.objects.create(owner_user=self.user1, name="My Movies")
|
|
self.assertEqual(lib.visibility, Library.Visibility.PRIVATE)
|
|
|
|
# Test unique constraint: Cannot have two libraries with the same name for the same user
|
|
with transaction.atomic():
|
|
with self.assertRaises(IntegrityError):
|
|
Library.objects.create(owner_user=self.user1, name="My Movies")
|
|
|
|
# Different user can have the same library name
|
|
lib2 = Library.objects.create(owner_user=self.user2, name="My Movies")
|
|
self.assertEqual(lib2.name, "My Movies")
|
|
|
|
def test_media_source_and_item(self):
|
|
lib = Library.objects.create(owner_user=self.user1, name="My Movies")
|
|
source = MediaSource.objects.create(
|
|
library=lib,
|
|
name="Local NAS",
|
|
source_type=MediaSource.SourceType.LOCAL_DIRECTORY,
|
|
uri="/mnt/nas/movies"
|
|
)
|
|
|
|
item = MediaItem.objects.create(
|
|
media_source=source,
|
|
title="Cool Movie",
|
|
item_kind=MediaItem.ItemKind.MOVIE,
|
|
runtime_seconds=7200,
|
|
file_path="/mnt/nas/movies/cool_movie.mp4"
|
|
)
|
|
|
|
self.assertEqual(item.runtime_seconds, 7200)
|
|
|
|
# Test unique constraint (same media source, same path)
|
|
with transaction.atomic():
|
|
with self.assertRaises(IntegrityError):
|
|
MediaItem.objects.create(
|
|
media_source=source,
|
|
title="Another Movie",
|
|
item_kind=MediaItem.ItemKind.MOVIE,
|
|
runtime_seconds=5000,
|
|
file_path="/mnt/nas/movies/cool_movie.mp4"
|
|
)
|
|
|
|
# Test M2M Genre works beautifully
|
|
genre1 = Genre.objects.create(name="Action")
|
|
genre2 = Genre.objects.create(name="Sci-Fi")
|
|
item.genres.add(genre1, genre2)
|
|
self.assertEqual(item.genres.count(), 2)
|
|
|
|
def test_channel_and_scheduling(self):
|
|
lib = Library.objects.create(owner_user=self.user1, name="TV Network")
|
|
channel = Channel.objects.create(
|
|
owner_user=self.user1,
|
|
library=lib,
|
|
name="Channel 1",
|
|
slug="ch-1",
|
|
channel_number=1
|
|
)
|
|
|
|
template = ScheduleTemplate.objects.create(
|
|
channel=channel,
|
|
name="Weekday Prime Time",
|
|
timezone_name="America/New_York"
|
|
)
|
|
|
|
block = ScheduleBlock.objects.create(
|
|
schedule_template=template,
|
|
name="8PM Movie",
|
|
block_type=ScheduleBlock.BlockType.PROGRAMMING,
|
|
start_local_time=time(20, 0),
|
|
end_local_time=time(22, 0),
|
|
day_of_week_mask=62 # Mon-Fri bitmask
|
|
)
|
|
|
|
self.assertEqual(block.pad_strategy, ScheduleBlock.PadStrategy.FILL_WITH_INTERSTITIALS)
|
|
|
|
def test_airing_constraints(self):
|
|
lib = Library.objects.create(owner_user=self.user1, name="TV Network")
|
|
source = MediaSource.objects.create(
|
|
library=lib,
|
|
name="Local NAS",
|
|
source_type=MediaSource.SourceType.LOCAL_DIRECTORY,
|
|
uri="/mnt/nas/tv"
|
|
)
|
|
item = MediaItem.objects.create(
|
|
media_source=source,
|
|
title="Promo",
|
|
item_kind=MediaItem.ItemKind.BUMPER,
|
|
runtime_seconds=15,
|
|
file_path="/mnt/nas/tv/promo.mp4"
|
|
)
|
|
channel = Channel.objects.create(
|
|
owner_user=self.user1,
|
|
library=lib,
|
|
name="Promo Channel",
|
|
slug="promo-ch",
|
|
channel_number=99
|
|
)
|
|
|
|
now = timezone.now()
|
|
airing = Airing.objects.create(
|
|
channel=channel,
|
|
media_item=item,
|
|
starts_at=now,
|
|
ends_at=now + timezone.timedelta(seconds=15),
|
|
slot_kind=Airing.SlotKind.BUMPER,
|
|
source_reason=Airing.SourceReason.MANUAL,
|
|
generation_batch_uuid=uuid4()
|
|
)
|
|
|
|
self.assertEqual(airing.status, Airing.Status.SCHEDULED)
|