Files
thrillwiki_django_no_react/backend/tests/services/test_ride_service.py

382 lines
12 KiB
Python

"""
Tests for RideService.
Following Django styleguide pattern: test__<context>__<action>__<expected_outcome>
"""
import pytest
from unittest.mock import Mock, patch, MagicMock
from django.test import TestCase
from django.core.exceptions import ValidationError
from apps.rides.services import RideService
from apps.rides.models import Ride
from tests.factories import (
ParkFactory,
RideFactory,
RideModelFactory,
ParkAreaFactory,
UserFactory,
ManufacturerCompanyFactory,
DesignerCompanyFactory,
)
@pytest.mark.django_db
class TestRideServiceCreateRide(TestCase):
"""Tests for RideService.create_ride."""
def test__create_ride__valid_data__creates_ride(self):
"""Test create_ride creates ride with valid data."""
park = ParkFactory()
user = UserFactory()
ride = RideService.create_ride(
name="Test Ride",
park_id=park.pk,
description="A test ride",
status="OPERATING",
category="TR",
created_by=user,
)
assert ride.name == "Test Ride"
assert ride.park == park
assert ride.description == "A test ride"
assert ride.status == "OPERATING"
assert ride.category == "TR"
def test__create_ride__with_manufacturer__sets_manufacturer(self):
"""Test create_ride sets manufacturer when provided."""
park = ParkFactory()
manufacturer = ManufacturerCompanyFactory()
ride = RideService.create_ride(
name="Test Ride",
park_id=park.pk,
category="RC",
manufacturer_id=manufacturer.pk,
)
assert ride.manufacturer == manufacturer
def test__create_ride__with_designer__sets_designer(self):
"""Test create_ride sets designer when provided."""
park = ParkFactory()
designer = DesignerCompanyFactory()
ride = RideService.create_ride(
name="Test Ride",
park_id=park.pk,
category="RC",
designer_id=designer.pk,
)
assert ride.designer == designer
def test__create_ride__with_ride_model__sets_ride_model(self):
"""Test create_ride sets ride model when provided."""
park = ParkFactory()
ride_model = RideModelFactory()
ride = RideService.create_ride(
name="Test Ride",
park_id=park.pk,
category="RC",
ride_model_id=ride_model.pk,
)
assert ride.ride_model == ride_model
def test__create_ride__with_park_area__sets_park_area(self):
"""Test create_ride sets park area when provided."""
park = ParkFactory()
area = ParkAreaFactory(park=park)
ride = RideService.create_ride(
name="Test Ride",
park_id=park.pk,
category="TR",
park_area_id=area.pk,
)
assert ride.park_area == area
def test__create_ride__invalid_park__raises_exception(self):
"""Test create_ride raises exception for invalid park."""
with pytest.raises(Exception):
RideService.create_ride(
name="Test Ride",
park_id=99999, # Non-existent
category="TR",
)
@pytest.mark.django_db
class TestRideServiceUpdateRide(TestCase):
"""Tests for RideService.update_ride."""
def test__update_ride__valid_updates__updates_ride(self):
"""Test update_ride updates ride with valid data."""
ride = RideFactory(name="Original Name", description="Original desc")
updated_ride = RideService.update_ride(
ride_id=ride.pk,
updates={"name": "Updated Name", "description": "Updated desc"},
)
assert updated_ride.name == "Updated Name"
assert updated_ride.description == "Updated desc"
def test__update_ride__partial_updates__updates_only_specified_fields(self):
"""Test update_ride only updates specified fields."""
ride = RideFactory(name="Original", status="OPERATING")
updated_ride = RideService.update_ride(
ride_id=ride.pk,
updates={"name": "New Name"},
)
assert updated_ride.name == "New Name"
assert updated_ride.status == "OPERATING" # Unchanged
def test__update_ride__nonexistent_ride__raises_exception(self):
"""Test update_ride raises exception for non-existent ride."""
with pytest.raises(Ride.DoesNotExist):
RideService.update_ride(
ride_id=99999,
updates={"name": "New Name"},
)
@pytest.mark.django_db
class TestRideServiceCloseRideTemporarily(TestCase):
"""Tests for RideService.close_ride_temporarily."""
def test__close_ride_temporarily__operating_ride__changes_status(self):
"""Test close_ride_temporarily changes status to CLOSED_TEMP."""
ride = RideFactory(status="OPERATING")
user = UserFactory()
result = RideService.close_ride_temporarily(ride_id=ride.pk, user=user)
assert result.status == "CLOSED_TEMP"
def test__close_ride_temporarily__nonexistent_ride__raises_exception(self):
"""Test close_ride_temporarily raises exception for non-existent ride."""
with pytest.raises(Ride.DoesNotExist):
RideService.close_ride_temporarily(ride_id=99999)
@pytest.mark.django_db
class TestRideServiceMarkRideSBNO(TestCase):
"""Tests for RideService.mark_ride_sbno."""
def test__mark_ride_sbno__operating_ride__changes_status(self):
"""Test mark_ride_sbno changes status to SBNO."""
ride = RideFactory(status="OPERATING")
user = UserFactory()
result = RideService.mark_ride_sbno(ride_id=ride.pk, user=user)
assert result.status == "SBNO"
@pytest.mark.django_db
class TestRideServiceScheduleRideClosing(TestCase):
"""Tests for RideService.schedule_ride_closing."""
def test__schedule_ride_closing__valid_data__schedules_closing(self):
"""Test schedule_ride_closing schedules ride closing."""
from datetime import date, timedelta
ride = RideFactory(status="OPERATING")
user = UserFactory()
closing_date = date.today() + timedelta(days=30)
result = RideService.schedule_ride_closing(
ride_id=ride.pk,
closing_date=closing_date,
post_closing_status="DEMOLISHED",
user=user,
)
assert result.status == "CLOSING"
assert result.closing_date == closing_date
assert result.post_closing_status == "DEMOLISHED"
@pytest.mark.django_db
class TestRideServiceCloseRidePermanently(TestCase):
"""Tests for RideService.close_ride_permanently."""
def test__close_ride_permanently__operating_ride__changes_status(self):
"""Test close_ride_permanently changes status to CLOSED_PERM."""
ride = RideFactory(status="OPERATING")
user = UserFactory()
result = RideService.close_ride_permanently(ride_id=ride.pk, user=user)
assert result.status == "CLOSED_PERM"
@pytest.mark.django_db
class TestRideServiceDemolishRide(TestCase):
"""Tests for RideService.demolish_ride."""
def test__demolish_ride__closed_ride__changes_status(self):
"""Test demolish_ride changes status to DEMOLISHED."""
ride = RideFactory(status="CLOSED_PERM")
user = UserFactory()
result = RideService.demolish_ride(ride_id=ride.pk, user=user)
assert result.status == "DEMOLISHED"
@pytest.mark.django_db
class TestRideServiceRelocateRide(TestCase):
"""Tests for RideService.relocate_ride."""
def test__relocate_ride__valid_data__relocates_ride(self):
"""Test relocate_ride moves ride to new park."""
old_park = ParkFactory()
new_park = ParkFactory()
ride = RideFactory(park=old_park, status="OPERATING")
user = UserFactory()
result = RideService.relocate_ride(
ride_id=ride.pk,
new_park_id=new_park.pk,
user=user,
)
assert result.park == new_park
assert result.status == "RELOCATED"
@pytest.mark.django_db
class TestRideServiceReopenRide(TestCase):
"""Tests for RideService.reopen_ride."""
def test__reopen_ride__closed_temp_ride__changes_status(self):
"""Test reopen_ride changes status to OPERATING."""
ride = RideFactory(status="CLOSED_TEMP")
user = UserFactory()
result = RideService.reopen_ride(ride_id=ride.pk, user=user)
assert result.status == "OPERATING"
@pytest.mark.django_db
class TestRideServiceHandleNewEntitySuggestions(TestCase):
"""Tests for RideService.handle_new_entity_suggestions."""
@patch("apps.rides.services.ModerationService.create_edit_submission_with_queue")
def test__handle_new_entity_suggestions__new_manufacturer__creates_submission(
self, mock_create_submission
):
"""Test handle_new_entity_suggestions creates submission for new manufacturer."""
mock_submission = Mock()
mock_submission.id = 1
mock_create_submission.return_value = mock_submission
user = UserFactory()
form_data = {
"manufacturer_search": "New Manufacturer",
"manufacturer": None,
"designer_search": "",
"designer": None,
"ride_model_search": "",
"ride_model": None,
}
result = RideService.handle_new_entity_suggestions(
form_data=form_data,
submitter=user,
)
assert result["total_submissions"] == 1
assert 1 in result["manufacturers"]
mock_create_submission.assert_called_once()
@patch("apps.rides.services.ModerationService.create_edit_submission_with_queue")
def test__handle_new_entity_suggestions__new_designer__creates_submission(
self, mock_create_submission
):
"""Test handle_new_entity_suggestions creates submission for new designer."""
mock_submission = Mock()
mock_submission.id = 2
mock_create_submission.return_value = mock_submission
user = UserFactory()
form_data = {
"manufacturer_search": "",
"manufacturer": None,
"designer_search": "New Designer",
"designer": None,
"ride_model_search": "",
"ride_model": None,
}
result = RideService.handle_new_entity_suggestions(
form_data=form_data,
submitter=user,
)
assert result["total_submissions"] == 1
assert 2 in result["designers"]
@patch("apps.rides.services.ModerationService.create_edit_submission_with_queue")
def test__handle_new_entity_suggestions__new_ride_model__creates_submission(
self, mock_create_submission
):
"""Test handle_new_entity_suggestions creates submission for new ride model."""
mock_submission = Mock()
mock_submission.id = 3
mock_create_submission.return_value = mock_submission
user = UserFactory()
manufacturer = ManufacturerCompanyFactory()
form_data = {
"manufacturer_search": "",
"manufacturer": manufacturer,
"designer_search": "",
"designer": None,
"ride_model_search": "New Model",
"ride_model": None,
}
result = RideService.handle_new_entity_suggestions(
form_data=form_data,
submitter=user,
)
assert result["total_submissions"] == 1
assert 3 in result["ride_models"]
def test__handle_new_entity_suggestions__no_new_entities__returns_empty(self):
"""Test handle_new_entity_suggestions with no new entities returns empty result."""
user = UserFactory()
manufacturer = ManufacturerCompanyFactory()
form_data = {
"manufacturer_search": "Existing Mfr",
"manufacturer": manufacturer, # Already selected
"designer_search": "",
"designer": None,
"ride_model_search": "",
"ride_model": None,
}
result = RideService.handle_new_entity_suggestions(
form_data=form_data,
submitter=user,
)
assert result["total_submissions"] == 0
assert len(result["manufacturers"]) == 0
assert len(result["designers"]) == 0
assert len(result["ride_models"]) == 0