"""Integration tests for PATCH /transfer/job/.""" import requests from .helpers import TIMEOUT, create_job, delete_job, url class TestUpdateTransferJob: """Tests for PATCH /transfer/job/.""" def test_updates_mutable_fields(self, qa_base_url, auth_headers, qa_project): """Returns 200 and persists status, sfn_execution_arn, and revenue_cutoff_date.""" job = create_job(qa_base_url, auth_headers, qa_project["project_id"]) job_id = job["project_transfer_job_id"] r = requests.patch( url(qa_base_url, f"/transfer/job/{job_id}"), headers=auth_headers, json={ "status": "PROCESSING", "sfn_execution_arn": "arn:aws:states:us-east-1:123456789012:execution:test", "revenue_cutoff_date": "2026-01-31", }, timeout=TIMEOUT, ) assert r.status_code == 200 body = r.json() assert body["status"] == "PROCESSING" assert body["sfn_execution_arn"] == ( "arn:aws:states:us-east-1:123456789012:execution:test" ) assert body["revenue_cutoff_date"] == "2026-01-31" def test_updates_status_to_failed_with_failure_reason( self, qa_base_url, auth_headers, qa_project): """Returns 200 and persists status=FAILED and failure_reason.""" job = create_job(qa_base_url, auth_headers, qa_project["project_id"]) job_id = job["project_transfer_job_id"] r = requests.patch( url(qa_base_url, f"/transfer/job/{job_id}"), headers=auth_headers, json={"status": "FAILED", "failure_reason": "SFN timed out"}, timeout=TIMEOUT, ) assert r.status_code == 200 body = r.json() assert body["status"] == "FAILED" assert body["failure_reason"] == "SFN timed out" def test_updates_status_to_completed_sets_transfer_completed_on( self, qa_base_url, auth_headers, qa_project): """Returns 200 and auto-populates transfer_completed_on when status=COMPLETED.""" job = create_job(qa_base_url, auth_headers, qa_project["project_id"]) job_id = job["project_transfer_job_id"] r = requests.patch( url(qa_base_url, f"/transfer/job/{job_id}"), headers=auth_headers, json={"status": "COMPLETED"}, timeout=TIMEOUT, ) assert r.status_code == 200 body = r.json() assert body["status"] == "COMPLETED" assert body["transfer_completed_on"] is not None def test_only_unknown_fields_returns_400(self, qa_base_url, auth_headers, qa_project): """Returns 400 when the body contains no recognised patchable fields.""" job = create_job(qa_base_url, auth_headers, qa_project["project_id"]) job_id = job["project_transfer_job_id"] try: r = requests.patch( url(qa_base_url, f"/transfer/job/{job_id}"), headers=auth_headers, json={"unknown_field": "value"}, timeout=TIMEOUT, ) assert r.status_code == 400 finally: delete_job(qa_base_url, auth_headers, job_id) def test_failed_status_without_failure_reason_returns_400( self, qa_base_url, auth_headers, qa_project): """Returns 400 when status=FAILED is sent without failure_reason.""" job = create_job(qa_base_url, auth_headers, qa_project["project_id"]) job_id = job["project_transfer_job_id"] try: r = requests.patch( url(qa_base_url, f"/transfer/job/{job_id}"), headers=auth_headers, json={"status": "FAILED"}, timeout=TIMEOUT, ) assert r.status_code == 400 finally: delete_job(qa_base_url, auth_headers, job_id) def test_updating_terminal_job_returns_400(self, qa_base_url, auth_headers, qa_project): """Returns 400 when attempting to update a job that is already in a terminal status.""" job = create_job(qa_base_url, auth_headers, qa_project["project_id"]) job_id = job["project_transfer_job_id"] # Move to COMPLETED — only QUEUED jobs can be deleted via API so no # delete_job call here; qa_project fixture teardown hard-deletes the row. requests.patch( url(qa_base_url, f"/transfer/job/{job_id}"), headers=auth_headers, json={"status": "COMPLETED"}, timeout=TIMEOUT, ) r = requests.patch( url(qa_base_url, f"/transfer/job/{job_id}"), headers=auth_headers, json={"status": "PROCESSING"}, timeout=TIMEOUT, ) assert r.status_code == 400 def test_missing_jwt_returns_401(self, qa_base_url, qa_project, auth_headers): """Returns 401 when no Authorization header is provided.""" job = create_job(qa_base_url, auth_headers, qa_project["project_id"]) job_id = job["project_transfer_job_id"] try: r = requests.patch( url(qa_base_url, f"/transfer/job/{job_id}"), headers={}, json={"status": "PROCESSING"}, timeout=TIMEOUT, ) assert r.status_code == 401 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.patch( url(qa_base_url, "/transfer/job/999999999"), headers=auth_headers, json={"status": "PROCESSING"}, timeout=TIMEOUT, ) assert r.status_code == 404