mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-23 17:51:09 -05:00
Add standardized HTMX conventions, interaction patterns, and migration guide for ThrillWiki UX
This commit is contained in:
381
backend/tests/services/test_ride_service.py
Normal file
381
backend/tests/services/test_ride_service.py
Normal file
@@ -0,0 +1,381 @@
|
||||
"""
|
||||
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
|
||||
Reference in New Issue
Block a user