🚧 WIP
This commit is contained in:
@@ -448,4 +448,104 @@ class TestConfigExportImport:
|
||||
assert r.status_code == 200 # export is a read
|
||||
r = await c.post("/api/config/import", json={"format": "wago-sim-config",
|
||||
"modules": ["750-430"]})
|
||||
assert r.status_code == 403
|
||||
|
||||
|
||||
class TestChannelRanges:
|
||||
async def test_default_range_in_layout(self, client):
|
||||
r = await client.get("/api/node")
|
||||
ai = next(c for m in r.json()["modules"] if m["index"] == 4
|
||||
for c in m["channels"] if c["kind"] == "ai")
|
||||
assert ai["range"] == {"min": 0, "max": 4095}
|
||||
# digital channels carry no range
|
||||
di = next(c for m in r.json()["modules"] if m["index"] == 0
|
||||
for c in m["channels"] if c["kind"] == "di")
|
||||
assert di["range"] is None
|
||||
|
||||
async def test_put_ranges_and_layout(self, client, app):
|
||||
r = await client.put("/api/config/channel-ranges", json={
|
||||
"channel_ranges": {"AI4.0": {"min": 0, "max": 32000},
|
||||
"AO5.0": {"min": 400, "max": 2000}},
|
||||
"persist": False,
|
||||
})
|
||||
assert r.status_code == 200
|
||||
# layout reflects the configured range
|
||||
r = await client.get("/api/node")
|
||||
ai = next(c for m in r.json()["modules"] if m["index"] == 4
|
||||
for c in m["channels"] if c["kind"] == "ai" and c["address"] == "AI4.0")
|
||||
assert ai["range"] == {"min": 0, "max": 32000}
|
||||
assert app.node.channel_range("ao", 5, 0) == (400, 2000)
|
||||
|
||||
async def test_default_range_dropped_from_store(self, client, app):
|
||||
r = await client.put("/api/config/channel-ranges", json={
|
||||
"channel_ranges": {"AI4.0": {"min": 0, "max": 4095}}, # == default
|
||||
"persist": False,
|
||||
})
|
||||
assert r.status_code == 200
|
||||
assert app.node.channel_ranges == {} # kept clean
|
||||
|
||||
async def test_range_validation(self, client):
|
||||
base = {"persist": False}
|
||||
r = await client.put("/api/config/channel-ranges", json={
|
||||
"channel_ranges": {"XX4.0": {"min": 0, "max": 100}}, **base})
|
||||
assert r.status_code == 400 # bad code
|
||||
r = await client.put("/api/config/channel-ranges", json={
|
||||
"channel_ranges": {"AI4.0": {"min": 100, "max": 50}}, **base})
|
||||
assert r.status_code == 400 # min >= max
|
||||
r = await client.put("/api/config/channel-ranges", json={
|
||||
"channel_ranges": {"AI4.0": {"min": 0, "max": 70000}}, **base})
|
||||
assert r.status_code == 400 # > 65535
|
||||
r = await client.put("/api/config/channel-ranges", json={
|
||||
"channel_ranges": {"AI4.0": {"min": 0}}, **base})
|
||||
assert r.status_code == 400 # missing max
|
||||
|
||||
async def test_ranges_persist_to_yaml(self, client, app, tmp_path):
|
||||
cfg_file = tmp_path / "node.yaml"
|
||||
app.node_config_path = str(cfg_file)
|
||||
r = await client.put("/api/config/channel-ranges", json={
|
||||
"channel_ranges": {"AI4.0": {"min": 0, "max": 32000}}, "persist": True,
|
||||
})
|
||||
assert r.status_code == 200
|
||||
text = cfg_file.read_text(encoding="utf-8")
|
||||
assert "channel_ranges:" in text
|
||||
assert "min: 0, max: 32000" in text
|
||||
# loads back
|
||||
from wago_sim.scenario.dsl import load_yaml, load_channel_ranges
|
||||
ranges = load_channel_ranges(load_yaml(cfg_file))
|
||||
assert ranges == {"AI4.0": (0, 32000)}
|
||||
|
||||
async def test_ranges_survive_module_save(self, client, app, tmp_path):
|
||||
app.node_config_path = str(tmp_path / "node.yaml")
|
||||
await client.put("/api/config/channel-ranges", json={
|
||||
"channel_ranges": {"AI4.0": {"min": 0, "max": 32000}}, "persist": True,
|
||||
})
|
||||
r = await client.put("/api/config/modules", json={
|
||||
"modules": ["750-430", "750-467"], "persist": True,
|
||||
})
|
||||
assert r.status_code == 200
|
||||
# AI_2 is at slot 1 now; the AI4.0 range became stale -> carried
|
||||
# over but no longer matches a channel; the store keeps it (names
|
||||
# semantics differ: stale name codes are dropped on import only)
|
||||
text = (tmp_path / "node.yaml").read_text(encoding="utf-8")
|
||||
assert "channel_ranges:" in text
|
||||
|
||||
async def test_export_import_carries_ranges(self, client, app, tmp_path):
|
||||
await client.put("/api/config/channel-ranges", json={
|
||||
"channel_ranges": {"AI4.0": {"min": 600, "max": 2000}}, "persist": False,
|
||||
})
|
||||
exported = (await client.get("/api/config/export")).json()
|
||||
assert exported["channel_ranges"]["AI4.0"] == {"min": 600, "max": 2000}
|
||||
app.node_config_path = str(tmp_path / "node.yaml")
|
||||
r = await client.post("/api/config/import", json=exported)
|
||||
assert r.status_code == 200
|
||||
assert app.node.channel_range("ai", 4, 0) == (600, 2000)
|
||||
text = (tmp_path / "node.yaml").read_text(encoding="utf-8")
|
||||
assert "min: 600, max: 2000" in text
|
||||
|
||||
async def test_readonly_blocks_ranges(self, app):
|
||||
ro = build_webui(app, user="admin", password="simu", readonly=True)
|
||||
transport = httpx.ASGITransport(app=ro)
|
||||
async with httpx.AsyncClient(transport=transport, base_url="http://test") as c:
|
||||
await c.post("/login", json={"user": "admin", "password": "simu"})
|
||||
r = await c.put("/api/config/channel-ranges", json={"channel_ranges": {}})
|
||||
assert r.status_code == 403
|
||||
Reference in New Issue
Block a user