mirror of
https://github.com/daniviga/django-ram.git
synced 2026-02-03 17:40:39 +01:00
372 lines
12 KiB
Python
372 lines
12 KiB
Python
from django.test import TestCase
|
|
from django.core.exceptions import ValidationError
|
|
from django.db import IntegrityError
|
|
|
|
from metadata.models import (
|
|
Manufacturer,
|
|
Company,
|
|
Scale,
|
|
RollingStockType,
|
|
Decoder,
|
|
Shop,
|
|
Tag,
|
|
calculate_ratio,
|
|
)
|
|
|
|
|
|
class ManufacturerTestCase(TestCase):
|
|
"""Test cases for Manufacturer model."""
|
|
|
|
def test_manufacturer_creation(self):
|
|
"""Test creating a manufacturer."""
|
|
manufacturer = Manufacturer.objects.create(
|
|
name="Blackstone Models",
|
|
category="model",
|
|
country="US",
|
|
website="https://www.blackstonemodels.com",
|
|
)
|
|
|
|
self.assertEqual(str(manufacturer), "Blackstone Models")
|
|
self.assertEqual(manufacturer.slug, "blackstone-models")
|
|
self.assertEqual(manufacturer.category, "model")
|
|
|
|
def test_manufacturer_slug_auto_generation(self):
|
|
"""Test that slug is automatically generated."""
|
|
manufacturer = Manufacturer.objects.create(
|
|
name="Baldwin Locomotive Works",
|
|
category="real",
|
|
)
|
|
|
|
self.assertEqual(manufacturer.slug, "baldwin-locomotive-works")
|
|
|
|
def test_manufacturer_unique_constraint(self):
|
|
"""Test that name+category must be unique."""
|
|
Manufacturer.objects.create(
|
|
name="Baldwin",
|
|
category="real",
|
|
)
|
|
|
|
# Should not be able to create another with same name+category
|
|
with self.assertRaises(IntegrityError):
|
|
Manufacturer.objects.create(
|
|
name="Baldwin",
|
|
category="real",
|
|
)
|
|
|
|
def test_manufacturer_different_categories(self):
|
|
"""Test that same name is allowed with different categories."""
|
|
Manufacturer.objects.create(
|
|
name="Baldwin",
|
|
category="real",
|
|
)
|
|
|
|
# Should be able to create with different category
|
|
manufacturer2 = Manufacturer.objects.create(
|
|
name="Alco",
|
|
category="model",
|
|
)
|
|
|
|
self.assertEqual(manufacturer2.name, "Alco")
|
|
self.assertIsNotNone(manufacturer2.pk)
|
|
|
|
def test_manufacturer_website_short(self):
|
|
"""Test website_short extracts domain."""
|
|
manufacturer = Manufacturer.objects.create(
|
|
name="Test Manufacturer",
|
|
category="model",
|
|
website="https://www.example.com/path",
|
|
)
|
|
|
|
self.assertEqual(manufacturer.website_short(), "example.com")
|
|
|
|
def test_manufacturer_ordering(self):
|
|
"""Test manufacturer ordering by category and slug."""
|
|
m1 = Manufacturer.objects.create(name="Zebra", category="model")
|
|
m2 = Manufacturer.objects.create(name="Alpha", category="accessory")
|
|
m3 = Manufacturer.objects.create(name="Beta", category="model")
|
|
|
|
manufacturers = list(Manufacturer.objects.all())
|
|
# Ordered by category, then slug
|
|
self.assertEqual(manufacturers[0], m2) # accessory comes first
|
|
self.assertTrue(manufacturers.index(m3) < manufacturers.index(m1))
|
|
|
|
|
|
class CompanyTestCase(TestCase):
|
|
"""Test cases for Company model."""
|
|
|
|
def test_company_creation(self):
|
|
"""Test creating a company."""
|
|
company = Company.objects.create(
|
|
name="RGS",
|
|
extended_name="Rio Grande Southern Railroad",
|
|
country="US",
|
|
freelance=False,
|
|
)
|
|
|
|
self.assertEqual(str(company), "RGS")
|
|
self.assertEqual(company.slug, "rgs")
|
|
self.assertEqual(company.extended_name, "Rio Grande Southern Railroad")
|
|
|
|
def test_company_slug_generation(self):
|
|
"""Test automatic slug generation."""
|
|
company = Company.objects.create(
|
|
name="Denver & Rio Grande Western",
|
|
country="US",
|
|
)
|
|
|
|
self.assertEqual(company.slug, "denver-rio-grande-western")
|
|
|
|
def test_company_unique_name(self):
|
|
"""Test that company name must be unique."""
|
|
Company.objects.create(name="RGS", country="US")
|
|
|
|
with self.assertRaises(IntegrityError):
|
|
Company.objects.create(name="RGS", country="GB")
|
|
|
|
def test_company_extended_name_pp(self):
|
|
"""Test extended name pretty print."""
|
|
company = Company.objects.create(
|
|
name="RGS",
|
|
extended_name="Rio Grande Southern Railroad",
|
|
country="US",
|
|
)
|
|
|
|
self.assertEqual(
|
|
company.extended_name_pp(),
|
|
"(Rio Grande Southern Railroad)"
|
|
)
|
|
|
|
def test_company_extended_name_pp_empty(self):
|
|
"""Test extended name pretty print when empty."""
|
|
company = Company.objects.create(name="RGS", country="US")
|
|
|
|
self.assertEqual(company.extended_name_pp(), "")
|
|
|
|
def test_company_freelance_flag(self):
|
|
"""Test freelance flag."""
|
|
company = Company.objects.create(
|
|
name="Fake Railroad",
|
|
country="US",
|
|
freelance=True,
|
|
)
|
|
|
|
self.assertTrue(company.freelance)
|
|
|
|
|
|
class ScaleTestCase(TestCase):
|
|
"""Test cases for Scale model."""
|
|
|
|
def test_scale_creation(self):
|
|
"""Test creating a scale."""
|
|
scale = Scale.objects.create(
|
|
scale="HOn3",
|
|
ratio="1:87",
|
|
tracks=10.5,
|
|
gauge="3 ft",
|
|
)
|
|
|
|
self.assertEqual(str(scale), "HOn3")
|
|
self.assertEqual(scale.slug, "hon3")
|
|
self.assertEqual(scale.ratio, "1:87")
|
|
self.assertEqual(scale.tracks, 10.5)
|
|
|
|
def test_scale_ratio_calculation(self):
|
|
"""Test automatic ratio_int calculation."""
|
|
scale = Scale.objects.create(
|
|
scale="HO",
|
|
ratio="1:87",
|
|
tracks=16.5,
|
|
)
|
|
|
|
# 1/87 * 10000 = 114.94...
|
|
self.assertAlmostEqual(scale.ratio_int, 114, delta=1)
|
|
|
|
def test_scale_ratio_validation_valid(self):
|
|
"""Test that valid ratios are accepted."""
|
|
ratios = ["1:87", "1:160", "1:22.5", "1:48"]
|
|
|
|
for ratio in ratios:
|
|
result = calculate_ratio(ratio)
|
|
self.assertIsInstance(result, (int, float))
|
|
|
|
def test_scale_ratio_validation_invalid(self):
|
|
"""Test that invalid ratios raise ValidationError."""
|
|
with self.assertRaises(ValidationError):
|
|
calculate_ratio("invalid")
|
|
|
|
with self.assertRaises(ValidationError):
|
|
calculate_ratio("1:0") # Division by zero
|
|
|
|
def test_scale_ordering(self):
|
|
"""Test scale ordering by ratio_int (descending)."""
|
|
s1 = Scale.objects.create(scale="G", ratio="1:22.5", tracks=45.0)
|
|
s2 = Scale.objects.create(scale="HO", ratio="1:87", tracks=16.5)
|
|
s3 = Scale.objects.create(scale="N", ratio="1:160", tracks=9.0)
|
|
|
|
scales = list(Scale.objects.all())
|
|
# Ordered by -ratio_int (larger ratios first)
|
|
self.assertEqual(scales[0], s1) # G scale (largest)
|
|
self.assertEqual(scales[1], s2) # HO scale
|
|
self.assertEqual(scales[2], s3) # N scale (smallest)
|
|
|
|
|
|
class RollingStockTypeTestCase(TestCase):
|
|
"""Test cases for RollingStockType model."""
|
|
|
|
def test_rolling_stock_type_creation(self):
|
|
"""Test creating a rolling stock type."""
|
|
stock_type = RollingStockType.objects.create(
|
|
type="Steam Locomotive",
|
|
category="locomotive",
|
|
order=1,
|
|
)
|
|
|
|
self.assertEqual(str(stock_type), "Steam Locomotive locomotive")
|
|
self.assertEqual(stock_type.slug, "steam-locomotive-locomotive")
|
|
|
|
def test_rolling_stock_type_unique_constraint(self):
|
|
"""Test that category+type must be unique."""
|
|
RollingStockType.objects.create(
|
|
type="Steam Locomotive",
|
|
category="locomotive",
|
|
order=1,
|
|
)
|
|
|
|
with self.assertRaises(IntegrityError):
|
|
RollingStockType.objects.create(
|
|
type="Steam Locomotive",
|
|
category="locomotive",
|
|
order=2,
|
|
)
|
|
|
|
def test_rolling_stock_type_ordering(self):
|
|
"""Test ordering by order field."""
|
|
t3 = RollingStockType.objects.create(
|
|
type="Caboose", category="railcar", order=3
|
|
)
|
|
t1 = RollingStockType.objects.create(
|
|
type="Steam", category="locomotive", order=1
|
|
)
|
|
t2 = RollingStockType.objects.create(
|
|
type="Boxcar", category="railcar", order=2
|
|
)
|
|
|
|
types = list(RollingStockType.objects.all())
|
|
self.assertEqual(types[0], t1)
|
|
self.assertEqual(types[1], t2)
|
|
self.assertEqual(types[2], t3)
|
|
|
|
|
|
class DecoderTestCase(TestCase):
|
|
"""Test cases for Decoder model."""
|
|
|
|
def setUp(self):
|
|
"""Set up test data."""
|
|
self.manufacturer = Manufacturer.objects.create(
|
|
name="ESU",
|
|
category="accessory",
|
|
country="DE",
|
|
)
|
|
|
|
def test_decoder_creation(self):
|
|
"""Test creating a decoder."""
|
|
decoder = Decoder.objects.create(
|
|
name="LokSound 5",
|
|
manufacturer=self.manufacturer,
|
|
version="5.0",
|
|
sound=True,
|
|
)
|
|
|
|
self.assertEqual(str(decoder), "ESU - LokSound 5")
|
|
self.assertTrue(decoder.sound)
|
|
|
|
def test_decoder_without_sound(self):
|
|
"""Test creating a non-sound decoder."""
|
|
decoder = Decoder.objects.create(
|
|
name="LokPilot 5",
|
|
manufacturer=self.manufacturer,
|
|
sound=False,
|
|
)
|
|
|
|
self.assertFalse(decoder.sound)
|
|
|
|
def test_decoder_ordering(self):
|
|
"""Test decoder ordering by manufacturer name and decoder name."""
|
|
man2 = Manufacturer.objects.create(
|
|
name="Digitrax",
|
|
category="accessory",
|
|
)
|
|
|
|
d1 = Decoder.objects.create(
|
|
name="LokSound 5",
|
|
manufacturer=self.manufacturer,
|
|
)
|
|
d2 = Decoder.objects.create(
|
|
name="DZ123",
|
|
manufacturer=man2,
|
|
)
|
|
d3 = Decoder.objects.create(
|
|
name="LokPilot 5",
|
|
manufacturer=self.manufacturer,
|
|
)
|
|
|
|
decoders = list(Decoder.objects.all())
|
|
# Ordered by manufacturer name, then decoder name
|
|
self.assertEqual(decoders[0], d2) # Digitrax
|
|
self.assertTrue(decoders.index(d3) < decoders.index(d1)) # LokPilot before LokSound
|
|
|
|
|
|
class ShopTestCase(TestCase):
|
|
"""Test cases for Shop model."""
|
|
|
|
def test_shop_creation(self):
|
|
"""Test creating a shop."""
|
|
shop = Shop.objects.create(
|
|
name="Caboose Hobbies",
|
|
country="US",
|
|
website="https://www.caboosehobbies.com",
|
|
on_line=True,
|
|
active=True,
|
|
)
|
|
|
|
self.assertEqual(str(shop), "Caboose Hobbies")
|
|
self.assertTrue(shop.on_line)
|
|
self.assertTrue(shop.active)
|
|
|
|
def test_shop_defaults(self):
|
|
"""Test shop default values."""
|
|
shop = Shop.objects.create(name="Local Shop")
|
|
|
|
self.assertTrue(shop.on_line) # Default True
|
|
self.assertTrue(shop.active) # Default True
|
|
|
|
def test_shop_offline(self):
|
|
"""Test creating an offline shop."""
|
|
shop = Shop.objects.create(
|
|
name="Brick and Mortar Store",
|
|
on_line=False,
|
|
)
|
|
|
|
self.assertFalse(shop.on_line)
|
|
|
|
|
|
class TagTestCase(TestCase):
|
|
"""Test cases for Tag model."""
|
|
|
|
def test_tag_creation(self):
|
|
"""Test creating a tag."""
|
|
tag = Tag.objects.create(
|
|
name="Narrow Gauge",
|
|
slug="narrow-gauge",
|
|
)
|
|
|
|
self.assertEqual(str(tag), "Narrow Gauge")
|
|
self.assertEqual(tag.slug, "narrow-gauge")
|
|
|
|
def test_tag_unique_name(self):
|
|
"""Test that tag name must be unique."""
|
|
Tag.objects.create(name="Narrow Gauge", slug="narrow-gauge")
|
|
|
|
with self.assertRaises(IntegrityError):
|
|
Tag.objects.create(name="Narrow Gauge", slug="narrow-gauge")
|