diff --git a/aiohasupervisor/models/jobs.py b/aiohasupervisor/models/jobs.py index 2ef6223..0389025 100644 --- a/aiohasupervisor/models/jobs.py +++ b/aiohasupervisor/models/jobs.py @@ -45,6 +45,7 @@ class JobError(ResponseData): type: str message: str + stage: str | None @dataclass(slots=True, frozen=True) diff --git a/tests/fixtures/jobs_info.json b/tests/fixtures/jobs_info.json index 3c6667f..ea27d8d 100644 --- a/tests/fixtures/jobs_info.json +++ b/tests/fixtures/jobs_info.json @@ -48,7 +48,8 @@ "errors": [ { "type": "BackupInvalidError", - "message": "Invalid password for backup cfddca18" + "message": "Invalid password for backup cfddca18", + "stage": "restore_backup" } ], "created": "2025-01-30T20:55:15.000000+00:00", diff --git a/tests/fixtures/jobs_info_no_stage.json b/tests/fixtures/jobs_info_no_stage.json new file mode 100644 index 0000000..3f9d509 --- /dev/null +++ b/tests/fixtures/jobs_info_no_stage.json @@ -0,0 +1,25 @@ +{ + "result": "ok", + "data": { + "ignore_conditions": ["free_space"], + "jobs": [ + { + "name": "test_job_error_no_stage", + "reference": "test123", + "uuid": "3febe59311f94d6ba36f6f9f73357ca9", + "progress": 0, + "stage": null, + "done": true, + "errors": [ + { + "type": "TestError", + "message": "Test error without stage field", + "stage": null + } + ], + "created": "2025-01-30T20:55:12.859349+00:00", + "child_jobs": [] + } + ] + } +} diff --git a/tests/test_jobs.py b/tests/test_jobs.py index a21b6f2..aa72a49 100644 --- a/tests/test_jobs.py +++ b/tests/test_jobs.py @@ -42,6 +42,7 @@ async def test_jobs_info( assert info.jobs[1].reference == "cfddca18" assert info.jobs[1].errors[0].type == "BackupInvalidError" assert info.jobs[1].errors[0].message == "Invalid password for backup cfddca18" + assert info.jobs[1].errors[0].stage == "restore_backup" async def test_jobs_set_options( @@ -112,3 +113,22 @@ async def test_jobs_delete_job( assert responses.requests.keys() == { ("DELETE", URL(f"{SUPERVISOR_URL}/jobs/2febe59311f94d6ba36f6f9f73357ca8")) } + + +async def test_jobs_info_backward_compatibility_no_stage( + responses: aioresponses, supervisor_client: SupervisorClient +) -> None: + """Test jobs info API with error lacking stage field for backward compatibility.""" + responses.get( + f"{SUPERVISOR_URL}/jobs/info", + status=200, + body=load_fixture("jobs_info_no_stage.json"), + ) + info = await supervisor_client.jobs.info() + assert info.ignore_conditions == [JobCondition.FREE_SPACE] + + assert info.jobs[0].name == "test_job_error_no_stage" + assert info.jobs[0].reference == "test123" + assert info.jobs[0].errors[0].type == "TestError" + assert info.jobs[0].errors[0].message == "Test error without stage field" + assert info.jobs[0].errors[0].stage is None