"""Tests for track spatial model.""" from datetime import datetime import sqlalchemy from backend.connectors import mysql from backend.constants import error from backend.models import track_spatial from backend.models.track_additional_isrc import TrackAdditionalIsrc from backend.models.track_additional_isrc import TrackAdditionalIsrcType from backend.models.track_spatial import TrackSpatial from tests.testutils import db @db.test_schema_no_seed def test_get_track_spatial_excludes_soft_deleted(): """Soft-deleted (deleted_at set) records are not returned by reads.""" db.merge_model_objects([ TrackSpatial( track_id=100, isrc='US1234567890', deleted_at=datetime(2026, 1, 1)) ]) spatial_result = track_spatial.get_track_spatial(100) assert not spatial_result assert error.ERROR_MESSAGE_TRACK_SPATIAL_NOT_FOUND in str(spatial_result.errors) @db.test_schema_no_seed def test_get_spatial_isrc_map_by_track_ids_excludes_soft_deleted(): """Soft-deleted records are dropped from the ISRC map.""" db.merge_model_objects([ TrackSpatial( track_id=100, isrc='US1234567890', deleted_at=datetime(2026, 1, 1)), TrackSpatial(track_id=101, isrc='US0987654321'), ]) result = track_spatial.get_spatial_isrc_map_by_track_ids([100, 101]) assert result assert result.message == {101: 'US0987654321'} @db.test_schema_no_seed def test_get_track_spatial_success(track_spatial_data): """Verify track spatial is retrieved from database.""" track_spatial.create_track_spatial(track_spatial_data) spatial_result = track_spatial.get_track_spatial(track_spatial_data['track_id']) assert spatial_result assert spatial_result.message['track_id'] == 100 assert spatial_result.message['isrc'] == 'US1234567890' @db.test_schema_no_seed def test_get_track_spatial_not_found(): """Verify error when getting non-existent spatial.""" spatial_result = track_spatial.get_track_spatial(999) assert not spatial_result assert spatial_result.errors assert error.ERROR_MESSAGE_TRACK_SPATIAL_NOT_FOUND in str(spatial_result.errors) @db.test_schema_no_seed def test_create_track_spatial_success(track_spatial_data): """Verify track spatial is created in database.""" spatial_result = track_spatial.create_track_spatial(track_spatial_data) assert spatial_result assert spatial_result.message['track_id'] == 100 assert spatial_result.message['isrc'] == 'US1234567890' assert 'created_at' in spatial_result.message assert 'updated_at' in spatial_result.message @db.test_schema_no_seed def test_create_track_spatial_invalid_track_id(track_spatial_data_invalid): """Verify error when creating with invalid track_id.""" spatial_result = track_spatial.create_track_spatial(track_spatial_data_invalid) assert not spatial_result assert spatial_result.errors @db.test_schema_no_seed def test_create_track_spatial_duplicate_track_id(track_spatial_data): """Verify error when creating duplicate spatial for same track.""" # Create first spatial spatial_result1 = track_spatial.create_track_spatial(track_spatial_data) assert spatial_result1 # Try to create duplicate track_spatial_data['isrc'] = 'USNEW1234567' spatial_result2 = track_spatial.create_track_spatial(track_spatial_data) assert not spatial_result2 assert spatial_result2.errors @db.test_schema_no_seed def test_update_track_spatial_success(track_spatial_data): """Verify track spatial is updated in database.""" # First create a spatial spatial_result = track_spatial.create_track_spatial(track_spatial_data) assert spatial_result # Now update it track_spatial_data['isrc'] = 'USNEW1234567' spatial_result = track_spatial.update_track_spatial(track_spatial_data) assert spatial_result assert spatial_result.message['isrc'] == 'USNEW1234567' @db.test_schema_no_seed def test_update_track_spatial_creates_when_missing(track_spatial_data): """Verify upsert: PUT creates a row when none exists for the track.""" spatial_result = track_spatial.update_track_spatial(track_spatial_data) assert spatial_result assert spatial_result.message['track_id'] == track_spatial_data['track_id'] assert spatial_result.message['isrc'] == track_spatial_data['isrc'] assert 'created_at' in spatial_result.message assert 'updated_at' in spatial_result.message @db.test_schema_no_seed def test_update_track_spatial_invalid_track_id(track_spatial_data_invalid): """Verify error when upserting with an invalid track_id.""" spatial_result = track_spatial.update_track_spatial(track_spatial_data_invalid) assert not spatial_result assert spatial_result.errors @db.test_schema_no_seed def test_delete_track_spatial_success(track_spatial_data): """Verify track spatial is deleted from database.""" # First create a spatial create_spatial_result = track_spatial.create_track_spatial(track_spatial_data) assert create_spatial_result # Now delete it delete_spatial_result = track_spatial.delete_track_spatial( track_spatial_data['track_id']) assert delete_spatial_result assert delete_spatial_result.status == 200 @db.test_schema_no_seed def test_delete_track_spatial_not_found(): """Verify error when deleting non-existent spatial.""" spatial_result = track_spatial.delete_track_spatial(999) assert not spatial_result assert spatial_result.errors assert error.ERROR_MESSAGE_TRACK_SPATIAL_NOT_FOUND in str(spatial_result.errors) @db.test_schema_no_seed def test_get_spatial_isrc_map_by_track_ids_success(track_spatial_data): """Should return mapping of track_id to isrc for matching records.""" track_spatial.create_track_spatial(track_spatial_data) result = track_spatial.get_spatial_isrc_map_by_track_ids([100]) assert result assert result.message == {100: 'US1234567890'} @db.test_schema_no_seed def test_get_spatial_isrc_map_by_track_ids_partial_match(track_spatial_data): """Should only include track_ids that have a spatial record.""" track_spatial.create_track_spatial(track_spatial_data) result = track_spatial.get_spatial_isrc_map_by_track_ids([100, 999]) assert result assert result.message == {100: 'US1234567890'} @db.test_schema_no_seed def test_get_spatial_isrc_map_by_track_ids_empty_input(): """Should return empty dict immediately when track_ids list is empty.""" result = track_spatial.get_spatial_isrc_map_by_track_ids([]) assert result assert result.message == {} @db.test_schema_no_seed def test_get_spatial_isrc_map_by_track_ids_empty(): """Should return empty dict when no records match.""" result = track_spatial.get_spatial_isrc_map_by_track_ids([999]) assert result assert result.message == {} # --- dual-write: every track_spatial write is mirrored to track_additional_isrc --- def _additional_isrc_rows(track_id): """Plain-dict snapshot of track_additional_isrc rows for a track.""" with mysql.db_session() as session: return [ {'isrc': row.isrc, 'type': row.type, 'deleted_at': row.deleted_at} for row in session.query(TrackAdditionalIsrc).filter( TrackAdditionalIsrc.track_id == track_id).all() ] def _track_spatial_count(track_id): with mysql.db_session() as session: return session.query(TrackSpatial).filter( TrackSpatial.track_id == track_id).count() @db.test_schema_no_seed def test_create_track_spatial_dual_writes_additional_isrc(): """Creating a spatial also writes one active atmos track_additional_isrc row.""" track_spatial.create_track_spatial({'track_id': 100, 'isrc': 'US1234567890'}) rows = _additional_isrc_rows(100) assert len(rows) == 1 assert rows[0]['type'] == 'atmos' assert rows[0]['isrc'] == 'US1234567890' assert rows[0]['deleted_at'] is None @db.test_schema_no_seed def test_delete_track_spatial_soft_deletes_additional_isrc(): """Delete hard-removes the track_spatial row but soft-deletes the new one.""" track_spatial.create_track_spatial({'track_id': 100, 'isrc': 'US1234567890'}) track_spatial.delete_track_spatial(100) assert _track_spatial_count(100) == 0 new_rows = _additional_isrc_rows(100) assert len(new_rows) == 1 assert new_rows[0]['deleted_at'] is not None @db.test_schema_no_seed def test_recreate_after_delete_restores_additional_isrc_to_new_isrc(): """Re-creating after a delete restores the single new-table row to the new ISRC.""" track_spatial.create_track_spatial({'track_id': 100, 'isrc': 'US1234567890'}) track_spatial.delete_track_spatial(100) track_spatial.create_track_spatial({'track_id': 100, 'isrc': 'USNEW1234567'}) new_rows = _additional_isrc_rows(100) assert len(new_rows) == 1 assert new_rows[0]['deleted_at'] is None assert new_rows[0]['isrc'] == 'USNEW1234567' @db.test_schema_no_seed def test_update_track_spatial_dual_writes_additional_isrc(): """Upsert (PUT) also writes the mirror carrying the new ISRC.""" track_spatial.update_track_spatial({'track_id': 100, 'isrc': 'US1234567890'}) rows = _additional_isrc_rows(100) assert len(rows) == 1 assert rows[0]['isrc'] == 'US1234567890' assert rows[0]['deleted_at'] is None @db.test_schema_no_seed def test_update_soft_deleted_track_spatial_keeps_mirror_soft_deleted(): """Upserting a soft-deleted track_spatial row keeps the mirror soft-deleted too (the mirror tracks the old row's deleted_at) instead of resurrecting it.""" db.merge_model_objects([ TrackSpatial( track_id=100, isrc='US1234567890', deleted_at=datetime(2026, 1, 1)), TrackAdditionalIsrc( track_id=100, type=TrackAdditionalIsrcType.ATMOS, isrc='US1234567890', deleted_at=datetime(2026, 1, 1)), ]) track_spatial.update_track_spatial({'track_id': 100, 'isrc': 'USNEW1234567'}) rows = _additional_isrc_rows(100) assert len(rows) == 1 assert rows[0]['isrc'] == 'USNEW1234567' assert rows[0]['deleted_at'] is not None @db.test_schema_no_seed def test_duplicate_create_returns_409_leaving_mirror_untouched(): """A duplicate create returns 409 and does not corrupt the mirror's ISRC.""" track_spatial.create_track_spatial({'track_id': 100, 'isrc': 'US1234567890'}) result = track_spatial.create_track_spatial( {'track_id': 100, 'isrc': 'USREJECTED12'}) assert not result assert result.status == 409 rows = _additional_isrc_rows(100) assert len(rows) == 1 assert rows[0]['isrc'] == 'US1234567890' @db.test_schema_no_seed def test_mirror_failure_surfaces_as_error_not_false_409(monkeypatch): """A constraint failure in the mirror write surfaces as a real error, not a misleading 'track spatial already exists' 409.""" def _raise(*args, **kwargs): raise sqlalchemy.exc.IntegrityError('mirror', None, Exception('boom')) monkeypatch.setattr( track_spatial.track_additional_isrc, 'mirror_create_or_restore', _raise) result = track_spatial.create_track_spatial( {'track_id': 100, 'isrc': 'US1234567890'}) assert not result assert result.status != 409 # The whole dual-write rolls back -- no half-written track_spatial row. assert _track_spatial_count(100) == 0