fix(measure): filtro stazione anche su barcode, avvio sequenza e task_execute (#24)
_recipe_allowed_at_station() riusa get_station_recipes() (stessa fonte di /measure/select) per lookup_barcode, start_sequence e task_execute: prima solo l'elenco filtrava, il barcode e i link diretti lasciavano misurare ricette non assegnate alla stazione. Ricetta non assegnata -> abort(403) con messaggio "ricetta non assegnata a questa stazione" (pagine, come già fa role_required) o JSON 403 (lookup-barcode). Aggiornati i test esistenti che ora richiedono get_station_recipes/STATION_CODE mockati. Backend (ruoli sui run, StationRecipeAssignment su open_run) resta al lotto A1. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -170,7 +170,15 @@ class TestTaskList:
|
||||
class TestStartSequence:
|
||||
"""GET /measure/start/<recipe_id> — the operator's way in."""
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def _station_configured(self, monkeypatch):
|
||||
# start_sequence() checks recipe-station assignment (#24); STATION_CODE
|
||||
# defaults to unset in the test env, so every test in this class needs it.
|
||||
monkeypatch.setattr("blueprints.measure.Config.STATION_CODE", "ST-TEST")
|
||||
|
||||
def test_start_goes_to_the_first_task(self, logged_in_client, mock_api_client):
|
||||
# start_sequence() only accepts a recipe assigned to this station (#24).
|
||||
mock_api_client.get_station_recipes.return_value = [{"id": 1}]
|
||||
mock_api_client.get.side_effect = api_get_router({
|
||||
"/api/recipes/1/tasks": [
|
||||
{"id": 31, "title": "Nota", "order_index": 1},
|
||||
@@ -186,6 +194,7 @@ class TestStartSequence:
|
||||
def test_start_remembers_the_traceability(self, logged_in_client, mock_api_client):
|
||||
"""The list used to be where lot and serial were stored; the sequence
|
||||
skips it, so the storing has to happen on the way in."""
|
||||
mock_api_client.get_station_recipes.return_value = [{"id": 1}]
|
||||
mock_api_client.get.side_effect = api_get_router({
|
||||
"/api/recipes/1/tasks": [{"id": 30, "title": "Prima", "order_index": 0}],
|
||||
"/api/recipes/1": {"id": 1, "code": "REC-001", "name": "Test Recipe"},
|
||||
@@ -200,6 +209,7 @@ class TestStartSequence:
|
||||
self, logged_in_client, mock_api_client,
|
||||
):
|
||||
"""Point 8 holds on this door too: it is a way into the measurement."""
|
||||
mock_api_client.get_station_recipes.return_value = [{"id": 1}]
|
||||
mock_api_client.get.side_effect = api_get_router({
|
||||
"/api/recipes/1/tasks": [{"id": 30, "title": "Prima", "order_index": 0}],
|
||||
"/api/recipes/1": {
|
||||
@@ -215,6 +225,7 @@ class TestStartSequence:
|
||||
def test_start_without_tasks_falls_back_to_the_list(
|
||||
self, logged_in_client, mock_api_client,
|
||||
):
|
||||
mock_api_client.get_station_recipes.return_value = [{"id": 1}]
|
||||
mock_api_client.get.side_effect = api_get_router({
|
||||
"/api/recipes/1/tasks": [],
|
||||
"/api/recipes/1": {"id": 1, "code": "REC-001", "name": "Test Recipe"},
|
||||
@@ -224,6 +235,18 @@ class TestStartSequence:
|
||||
assert resp.status_code == 302
|
||||
assert resp.headers["Location"].endswith("/measure/tasks/1")
|
||||
|
||||
def test_start_refuses_recipe_not_assigned_to_station(
|
||||
self, logged_in_client, mock_api_client,
|
||||
):
|
||||
"""#24: a recipe not on this station's list cannot be started via a direct link."""
|
||||
mock_api_client.get_station_recipes.return_value = [{"id": 99}]
|
||||
mock_api_client.get.side_effect = api_get_router({
|
||||
"/api/recipes/1": {"id": 1, "code": "REC-001", "name": "Test Recipe"},
|
||||
})
|
||||
|
||||
resp = logged_in_client.get("/measure/start/1")
|
||||
assert resp.status_code == 403
|
||||
|
||||
|
||||
class TestTaskComplete:
|
||||
"""GET /measure/complete/<recipe_id> tests."""
|
||||
|
||||
Reference in New Issue
Block a user