From aede45cd98e819b2e1e4a4c55119d339fc0cc615 Mon Sep 17 00:00:00 2001 From: "F.N. Claessen" Date: Sun, 12 Jul 2026 06:25:07 +0200 Subject: [PATCH] test: lock in compatibility with FlexMeasures API v3.0-32 job responses FlexMeasures is moving to consistent 202 (Accepted) responses for asynchronous job handling (FlexMeasures/flexmeasures#2171): - trigger endpoints respond 202 ACCEPTED with job_id and job_monitor_url (previously 200 PROCESSED) - GET /sensors//schedules/ responds 202 while the job is pending and 422 with a failure message when the job failed (previously 400 UNKNOWN_SCHEDULE for both) The client already handles all of this - check_for_status() accepts any 2xx and check_response() polls on 202 GET responses - so these tests just pin that behavior against regressions, while the existing tests keep covering older servers (200 triggers, 400-while-pending polling). Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_0199yMJvFFPK5HyQRJAMpHpU Signed-off-by: F.N. Claessen --- tests/client/test_schedule.py | 62 +++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/tests/client/test_schedule.py b/tests/client/test_schedule.py index 0599207b..4cadb914 100644 --- a/tests/client/test_schedule.py +++ b/tests/client/test_schedule.py @@ -1003,3 +1003,65 @@ def test_convert_units_unsupported(): with pytest.raises(NotImplementedError, match="Power conversion from MW to °C"): convert_units([1.0], "MW", "°C") + + +@pytest.mark.asyncio +async def test_trigger_schedule_accepts_202_accepted() -> None: + """FlexMeasures API v3.0-32+ responds to trigger requests with + 202 (Accepted) and job info, instead of 200 (PROCESSED).""" + with aioresponses() as m: + flexmeasures_client = FlexMeasuresClient( + email="test@test.test", password="test" + ) + flexmeasures_client.access_token = "test-token" + m.post( + "http://localhost:5000/api/v3_0/assets/5/schedules/trigger", + status=202, + payload={ + "schedule": "test_schedule_id", + "job_id": "test_schedule_id", + "job_monitor_url": "/api/v3_0/jobs/test_schedule_id", + "status": "ACCEPTED", + "message": "Request has been accepted for processing.", + }, + ) + + schedule_id = await flexmeasures_client.trigger_schedule( + asset_id=5, + start="2023-03-26T10:00+02:00", + duration="PT12H", + flex_model=[{"sensor": 3, "soc-at-start": "50 kWh"}], + ) + + assert schedule_id == "test_schedule_id" + await flexmeasures_client.close() + + +@pytest.mark.asyncio +async def test_get_schedule_failed_job_raises() -> None: + """FlexMeasures API v3.0-32+ reports a failed scheduling job with + 422 and a failure message (previously 400 UNKNOWN_SCHEDULE), which + should surface as an error rather than being polled forever.""" + url = "http://localhost:5000/api/v3_0/sensors/1/schedules/some-uuid?duration=P0DT0H45M0S" # noqa: E501 + with aioresponses() as m: + m.get( + url=url, + status=422, + payload={ + "status": "FAILED", + "message": "Scheduling job failed with ValueError: prices unknown", + }, + ) + flexmeasures_client = FlexMeasuresClient( + email="test@test.test", + password="test", + request_timeout=2, + polling_interval=0.2, + access_token="skip-auth", + ) + + with pytest.raises(ValueError, match="prices unknown"): + await flexmeasures_client.get_schedule( + sensor_id=1, schedule_id="some-uuid", duration="PT45M" + ) + await flexmeasures_client.close()