"""Integration tests for POST /transfer/job//execute-content-transfer.""" import requests from .helpers import ( DESTINATION_SUBACCOUNT_ID, DESTINATION_VENDOR_ID, DESTINATION_VENDOR_ID_WITH_SUBACCOUNT, TIMEOUT, create_job, delete_job, set_destination_artists, url, ) class TestExecuteContentTransfer: """Tests for POST /transfer/job//execute-content-transfer.""" def test_executes_content_transfer( self, qa_base_url, auth_headers, qa_project, qa_destination_artist_id, db_connection): """Returns 200 and updates project, releases with destination vendor and artist.""" job = create_job(qa_base_url, auth_headers, qa_project["project_id"]) job_id = job["project_transfer_job_id"] try: set_destination_artists( qa_base_url, auth_headers, job_id, job["products"], qa_destination_artist_id ) r = requests.post( url(qa_base_url, f"/transfer/job/{job_id}/execute-content-transfer"), headers=auth_headers, timeout=TIMEOUT, ) assert r.status_code == 200 body = r.json() assert body["project_updated"] == 1 assert body["releases_updated"] == len(job["products"]) assert body["video_rows_updated"] == 0 assert body["release_artist_rows_updated"] == 0 assert body["track_artist_rows_updated"] == 0 assert body["track_writer_rows_updated"] == 0 # Confirm DB writes — GET /project returns 403 after transfer (project # now belongs to the destination vendor, not the originating vendor). with db_connection.cursor() as cur: cur.execute( "SELECT vendor_id, artist_id FROM project WHERE project_id = %s", (qa_project["project_id"],), ) project_row = cur.fetchone() cur.execute( "SELECT artist_id FROM releases WHERE release_id = %s", (qa_project["release_id"],), ) release_row = cur.fetchone() assert project_row["vendor_id"] == DESTINATION_VENDOR_ID assert project_row["artist_id"] == qa_destination_artist_id assert release_row["artist_id"] == qa_destination_artist_id finally: delete_job(qa_base_url, auth_headers, job_id) def test_nonexistent_job_returns_404(self, qa_base_url, auth_headers): """Returns 404 when the job does not exist.""" r = requests.post( url(qa_base_url, "/transfer/job/999999999/execute-content-transfer"), headers=auth_headers, timeout=TIMEOUT, ) assert r.status_code == 404 def test_soft_deleted_job_returns_404(self, qa_base_url, auth_headers, qa_project): """Returns 404 when the job has been soft-deleted.""" job = create_job(qa_base_url, auth_headers, qa_project["project_id"]) job_id = job["project_transfer_job_id"] delete_job(qa_base_url, auth_headers, job_id) r = requests.post( url(qa_base_url, f"/transfer/job/{job_id}/execute-content-transfer"), headers=auth_headers, timeout=TIMEOUT, ) assert r.status_code == 404 def test_soft_deleted_products_returns_400( self, qa_base_url, auth_headers, qa_project, db_connection): """Returns 400 when all product_transfer_history rows for the job are soft-deleted.""" job = create_job(qa_base_url, auth_headers, qa_project["project_id"]) job_id = job["project_transfer_job_id"] try: with db_connection.cursor() as cur: cur.execute( "UPDATE product_transfer_history SET deleted_at = NOW() " "WHERE job_id = %s", (job_id,), ) db_connection.commit() r = requests.post( url(qa_base_url, f"/transfer/job/{job_id}/execute-content-transfer"), headers=auth_headers, timeout=TIMEOUT, ) assert r.status_code == 400 finally: delete_job(qa_base_url, auth_headers, job_id) def test_missing_destination_artist_returns_422( self, qa_base_url, auth_headers, qa_project): """Returns 422 when destination_artist_id is not populated on snapshot rows.""" job = create_job(qa_base_url, auth_headers, qa_project["project_id"]) job_id = job["project_transfer_job_id"] try: r = requests.post( url(qa_base_url, f"/transfer/job/{job_id}/execute-content-transfer"), headers=auth_headers, timeout=TIMEOUT, ) assert r.status_code == 422 assert str(qa_project["release_id"]) in r.text finally: delete_job(qa_base_url, auth_headers, job_id) def test_executes_content_transfer_with_subaccount( self, qa_base_url, auth_headers, qa_project, qa_destination_subaccount_artist_id, db_connection): """Returns 200 and writes destination subaccount_id to project and releases.""" job = create_job( qa_base_url, auth_headers, qa_project["project_id"], destination_vendor_id=DESTINATION_VENDOR_ID_WITH_SUBACCOUNT, destination_subaccount_id=DESTINATION_SUBACCOUNT_ID, ) job_id = job["project_transfer_job_id"] try: set_destination_artists( qa_base_url, auth_headers, job_id, job["products"], qa_destination_subaccount_artist_id, ) r = requests.post( url(qa_base_url, f"/transfer/job/{job_id}/execute-content-transfer"), headers=auth_headers, timeout=TIMEOUT, ) assert r.status_code == 200 body = r.json() assert body["project_updated"] == 1 assert body["releases_updated"] == len(job["products"]) assert body["video_rows_updated"] == 0 assert body["release_artist_rows_updated"] == 0 assert body["track_artist_rows_updated"] == 0 assert body["track_writer_rows_updated"] == 0 # Confirm DB writes — GET /project returns 403 after transfer (project # now belongs to the destination vendor, not the originating vendor). with db_connection.cursor() as cur: cur.execute( "SELECT vendor_id, subaccount_id, artist_id FROM project WHERE project_id = %s", (qa_project["project_id"],), ) project_row = cur.fetchone() cur.execute( "SELECT artist_id, subaccount_id FROM releases WHERE release_id = %s", (qa_project["release_id"],), ) release_row = cur.fetchone() assert project_row["vendor_id"] == DESTINATION_VENDOR_ID_WITH_SUBACCOUNT assert project_row["subaccount_id"] == DESTINATION_SUBACCOUNT_ID assert project_row["artist_id"] == qa_destination_subaccount_artist_id assert release_row["artist_id"] == qa_destination_subaccount_artist_id assert release_row["subaccount_id"] == DESTINATION_SUBACCOUNT_ID finally: delete_job(qa_base_url, auth_headers, job_id) def test_executes_content_transfer_multiple_releases( self, qa_base_url, auth_headers, qa_project_multiple_releases, qa_artist_id): """Returns 200 and updates all releases when the project has multiple.""" job = create_job(qa_base_url, auth_headers, qa_project_multiple_releases["project_id"]) job_id = job["project_transfer_job_id"] try: set_destination_artists( qa_base_url, auth_headers, job_id, job["products"], qa_artist_id ) r = requests.post( url(qa_base_url, f"/transfer/job/{job_id}/execute-content-transfer"), headers=auth_headers, timeout=TIMEOUT, ) assert r.status_code == 200 body = r.json() assert body["project_updated"] == 1 assert body["releases_updated"] == len(qa_project_multiple_releases["release_ids"]) assert body["video_rows_updated"] == 0 assert body["release_artist_rows_updated"] == 0 assert body["track_artist_rows_updated"] == 0 assert body["track_writer_rows_updated"] == 0 finally: delete_job(qa_base_url, auth_headers, job_id) def test_executes_content_transfer_updates_product_video( self, qa_base_url, auth_headers, qa_project_with_video, qa_artist_id, db_connection): """Returns 200 with video_rows_updated=1 and updates primary_artist_id on product_video.""" job = create_job(qa_base_url, auth_headers, qa_project_with_video["project_id"]) job_id = job["project_transfer_job_id"] release_id = qa_project_with_video["release_id"] try: set_destination_artists( qa_base_url, auth_headers, job_id, job["products"], qa_artist_id ) # No API exists to set destination_video_artist_id — write it directly with db_connection.cursor() as cur: cur.execute( "UPDATE product_transfer_history " "SET destination_video_artist_id = %s " "WHERE job_id = %s AND release_id = %s", (qa_artist_id, job_id, release_id), ) db_connection.commit() r = requests.post( url(qa_base_url, f"/transfer/job/{job_id}/execute-content-transfer"), headers=auth_headers, timeout=TIMEOUT, ) assert r.status_code == 200 body = r.json() assert body["project_updated"] == 1 assert body["releases_updated"] == 1 assert body["video_rows_updated"] == 1 assert body["release_artist_rows_updated"] == 0 assert body["track_artist_rows_updated"] == 0 assert body["track_writer_rows_updated"] == 0 # Confirm primary_artist_id was updated on product_video with db_connection.cursor() as cur: cur.execute( "SELECT primary_artist_id FROM product_video WHERE release_id = %s", (release_id,), ) row = cur.fetchone() assert row["primary_artist_id"] == qa_artist_id finally: delete_job(qa_base_url, auth_headers, job_id)