fix(iace): Initialize pipeline reads operational_states from metadata

The Betriebszustand-UI saved states to metadata.operational_states but
the initialize handler only read states from the parsed narrative text.
Now merges both sources so the UI selection actually affects which
patterns fire during initialization.

Added integration E2E test that verifies: 2 states → fewer patterns,
9 states → more patterns.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-05-11 08:19:53 +02:00
parent cc919eb608
commit 285b74382a
2 changed files with 129 additions and 2 deletions
@@ -415,3 +415,86 @@ for (const project of PROJECTS) {
})
})
}
// ---------------------------------------------------------------------------
// 10. Integration: Operational States → Initialize → Hazards affected
// ---------------------------------------------------------------------------
test.describe('Integration: Op. States affect initialization', () => {
test.setTimeout(120_000)
const API = 'https://macmini:8093/sdk/v1/iace'
const HEADERS = { 'Content-Type': 'application/json', 'X-Tenant-Id': '9282a473-5c95-4b3a-bf78-0ecc0ec71d3e' }
// Use Cobot project — has limits_form data for initialization
const PROJECT_ID = PROJECTS[1].id
test('saving states to metadata and re-initializing changes pattern count', async ({ request }) => {
// Step 1: Get current project metadata
const projRes = await request.get(`${API}/projects/${PROJECT_ID}`, { headers: HEADERS })
expect(projRes.ok()).toBeTruthy()
const project = await projRes.json()
const existingMeta = project.metadata || {}
// Step 2: Save operational states with only 2 states (restrictive)
const restrictiveStates = ['automatic_operation', 'emergency_stop']
const putRes = await request.put(`${API}/projects/${PROJECT_ID}`, {
headers: HEADERS,
data: { metadata: { ...existingMeta, operational_states: restrictiveStates } },
})
expect(putRes.ok()).toBeTruthy()
// Step 3: Delete existing hazards + mitigations so initialize creates fresh ones
const hazRes = await request.get(`${API}/projects/${PROJECT_ID}/hazards`, { headers: HEADERS })
if (hazRes.ok()) {
const hazards = (await hazRes.json()).hazards || []
for (const h of hazards) {
await request.delete(`${API}/projects/${PROJECT_ID}/hazards/${h.id}`, { headers: HEADERS })
}
}
const mitRes = await request.get(`${API}/projects/${PROJECT_ID}/mitigations`, { headers: HEADERS })
if (mitRes.ok()) {
const mits = (await mitRes.json()).mitigations || []
for (const m of mits) {
await request.delete(`${API}/projects/${PROJECT_ID}/mitigations/${m.id}`, { headers: HEADERS })
}
}
// Step 4: Initialize with restrictive states
const initRes = await request.post(`${API}/projects/${PROJECT_ID}/initialize`, { headers: HEADERS })
expect(initRes.ok()).toBeTruthy()
const initData = await initRes.json()
const restrictivePatterns = initData.steps?.find((s: { name: string }) => s.name === 'Patterns abgeglichen')?.count || 0
// Step 5: Now widen to all 9 states
const allStates = [
'startup', 'homing', 'automatic_operation', 'manual_operation',
'teach_mode', 'maintenance', 'cleaning', 'emergency_stop', 'recovery_mode',
]
await request.put(`${API}/projects/${PROJECT_ID}`, {
headers: HEADERS,
data: { metadata: { ...existingMeta, operational_states: allStates } },
})
// Step 6: Delete hazards again and re-initialize
const hazRes2 = await request.get(`${API}/projects/${PROJECT_ID}/hazards`, { headers: HEADERS })
if (hazRes2.ok()) {
const hazards = (await hazRes2.json()).hazards || []
for (const h of hazards) {
await request.delete(`${API}/projects/${PROJECT_ID}/hazards/${h.id}`, { headers: HEADERS })
}
}
const initRes2 = await request.post(`${API}/projects/${PROJECT_ID}/initialize`, { headers: HEADERS })
expect(initRes2.ok()).toBeTruthy()
const initData2 = await initRes2.json()
const widePatterns = initData2.steps?.find((s: { name: string }) => s.name === 'Patterns abgeglichen')?.count || 0
// More states should match more (or equal) patterns
expect(widePatterns).toBeGreaterThanOrEqual(restrictivePatterns)
// Step 7: Restore original metadata
await request.put(`${API}/projects/${PROJECT_ID}`, {
headers: HEADERS,
data: { metadata: existingMeta },
})
})
})